当前位置: 首页 > news >正文

网站店铺的图片怎么做的seo网站自动发布外链工具

网站店铺的图片怎么做的,seo网站自动发布外链工具,项目外包,社保局网站建设意义系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现(一) HarmonyOS Next 系列之验证码输入组件实现(二) HarmonyOS Next 系列之底部标签栏TabBar实现(三) HarmonyOS Next 系列之HTTP请求封装和Token…

系列文章目录

HarmonyOS Next 系列之省市区弹窗选择器实现(一)
HarmonyOS Next 系列之验证码输入组件实现(二)
HarmonyOS Next 系列之底部标签栏TabBar实现(三)
HarmonyOS Next 系列之HTTP请求封装和Token持久化存储(四)
HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)


文章目录

  • 系列文章目录
  • 前言
  • 一、实现步骤总结
  • 二、代码实现
    • 1.媒体读写权限检查和申请
    • 2.从手机存储选择图片或拍照
    • 3.复制图片到缓存目录下
    • 4. 接口请求上传图片
  • 三、完整代码
    • 页面调用:


前言

HarmonyOS Next(基于API11)实现从手机选择图片或拍照上传功能,常用于头像上传等操作


一、实现步骤总结

1、媒体读写权限检查和申请
2、从手机存储选择图片或拍照
3、把图片复制到缓存目录
4、接口请求上传图片

分析说明:
图片上传使用API request.uploadFile 而该api上传文件的本地路径只支持internal协议

在这里插入图片描述

所以选择完图片/或拍照后需要把图片从内部存储复制到cache目录下,该操作需要外部存储设备媒体读写权限,且是用户级别的权限,因此每次复制图片前需要检查权限如果没权限需弹窗口让用户授权,最后在通过该api实现上传

在这里插入图片描述

二、代码实现

1.媒体读写权限检查和申请

(1)检查权限

工具类文件:

import bundleManager from '@ohos.bundle.bundleManager';
import abilityAccessCtrl, { Context, Permissions } from '@ohos.abilityAccessCtrl';//校验应用是否授予权限
//@params permissions:权限名称数组
//@return permissionabilityAccessCtrl:权限名称
async function checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {let atManager = abilityAccessCtrl.createAtManager();let grantStatus: abilityAccessCtrl.GrantStatus = 0;// 获取应用程序的accessTokenIDlet tokenId: number = 0;try {let bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;tokenId = appInfo.accessTokenId;} catch (err) {console.error(`getBundleInfoForSelf failed, code is ${err.code}, message is ${err.message}`);}// 校验应用是否被授予权限try {grantStatus = await atManager.checkAccessToken(tokenId, permission);} catch (err) {console.error(`checkAccessToken failed, code is ${err.code}, message is ${err.message}`);}return grantStatus;
}//检查用户权限
//@params permissions:权限名称数组
export  async function checkPermissions(permissions: Permissions): Promise<boolean> {try {let grantStatus: abilityAccessCtrl.GrantStatus = await checkAccessToken(permissions);return grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED}catch (e) {return Promise.reject(e)}
}

调用:

      const READ_MEDIA_PERMISSION: Permissions = 'ohos.permission.READ_MEDIA' //媒体读取权限const WRITE_MEDIA_PERMISSION: Permissions = 'ohos.permission.WRITE_MEDIA' //媒体写入权限let permissionList: Permissions[] = []; //需要申请选项列表let readPermission = await checkPermissions(READ_MEDIA_PERMISSION)//检查是否有媒体读取权限!readPermission && permissionList.push(READ_MEDIA_PERMISSION)let writePermission = await checkPermissions(WRITE_MEDIA_PERMISSION)//检查是否有媒体写入权限!writePermission && permissionList.push(READ_MEDIA_PERMISSION)

(2)申请权限
工具类文件:

import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
import common from '@ohos.app.ability.common'interface rejectObj {code: numbermessage: string
}
/*** 申请权限* @params context:AblitiyContext* @params permissions:权限名称数组* @returns  Promise<boolean>:是否授权成功*/
export async function applyPermission(context: common.UIAbilityContext, permissions: Array<Permissions>): Promise<boolean> {let atManager = abilityAccessCtrl.createAtManager();return new Promise((resolve: (res: boolean) => void, reject: (e: rejectObj) => void) => {atManager.requestPermissionsFromUser(context, permissions).then((data) => {let grantStatus: Array<number> = data.authResults;resolve(grantStatus.every(item => item === 0))}).catch((err: rejectObj) => {reject(err)})})
}

调用:

       private context = getContext(this) as common.UIAbilityContext; //UIAbilityContext...............//申请权限let res: boolean = await applyPermission(this.context, permissionList)if (!res) {//用户未同意授权AlertDialog.show({title: "提示",message: "无权限读写用户外部存储中的媒体文件信息,请前往系统设置开启",alignment: DialogAlignment.Center,secondaryButton: {value: '关闭',action: () => {}}})}

2.从手机存储选择图片或拍照

(1)从手机存储选择图片

    import picker from '@ohos.file.picker';........//从相册选择let PhotoSelectOptions = new picker.PhotoSelectOptions();PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;PhotoSelectOptions.maxSelectNumber = 1;let photoPicker = new picker.PhotoViewPicker();photoPicker.select(PhotoSelectOptions).then(async (PhotoSelectResult) => {if (PhotoSelectResult.photoUris.length) {console.log(`图片本地路径:${PhotoSelectResult.photoUris[0]}`)} })

(2)拍照

    import camera from '@ohos.multimedia.camera';import camerapicker from '@ohos.multimedia.cameraPicker';import { BusinessError } from '@ohos.base';........try{let pickerProfile: camerapicker.PickerProfile = {cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK};let pickerResult: camerapicker.PickerResult = await camerapicker.pick(this.context,[camerapicker.PickerMediaType.PHOTO, camerapicker.PickerMediaType.PHOTO], pickerProfile);} catch (error) {let err = error as BusinessError;console.error(`the pick call failed. error code: ${err.code}`);}   

3.复制图片到缓存目录下

默认复制图片到缓存目录cache根路径下,移动后文件名前面加上当前时间戳区分:timestamep+原name.格式

import fs from '@ohos.file.fs';/*** 复制文件到缓存目录下* @param path :文件路径* @param context :Context* @returns Promise<string> 移动后文件路径*/
export async function copyFileToCache(path: string,context:Context): Promise<string> {try {let file =  fs.openSync(path, fs.OpenMode.READ_WRITE)if (file) {let fileDir: string = `${context.cacheDir}` //临时文件目录//时间戳生成随机文件名let newPath: string =  `${new Date().getTime()}_${path.split("/")[path.split("/").length-1]}`let targetPath: string = `${fileDir}/${newPath}`fs.copyFileSync(file.fd, targetPath)return  newPath}else {return ''}} catch (e) {return Promise.resolve('')}
}

4. 接口请求上传图片

  //开始上传图片 path:图片路径后缀(图片名称)async uploadImage(path: string) {let uri=`internal://cache/${path}` //上传图片全路径let uploadConfig: request.UploadConfig = {url:"http://xxxxxxx",header:{},method: "POST",files: [{ filename: path, name: "file", uri, type: path.split('.')[path.split('.').length-1] }],data: [],};try {let uploadTask:request.UploadTask=await request.uploadFile(this.context, uploadConfig)//上传中回调uploadTask.on('progress', (size,total) => {console.log(size.toString(),total.toString(),'上传进度')})//上传完成回调uploadTask.on('complete', (taskStates: request.TaskState[]) => {console.info("upOnComplete complete taskState:" + JSON.stringify(taskStates));})//上传失败回调uploadTask.on('fail', (taskStates: request.TaskState[]) => {console.info("upOnComplete fail taskState:" + JSON.stringify(taskStates));})}catch (e){console.log( JSON.stringify(e),'e')}}

需要注意的是我们在复制图片步骤中通过context.cacheDir获取到的缓存目录路径如下所示:

"path":"/data/storage/el2/base/haps/entry/cache/1717854801890_IMG_20240603_170235.jpg"

需转换成internal协议路径,
前面 “/data/storage/el2/base/haps/entry/cache"实际等价于"internal://cache”
所以在上传接口拼接uri参数时候只需要知道图片名称+格式即可,最终上传参数拼接后路径为internal://cache/1717854801890_IMG_20240603_170235.jpg


三、完整代码

完整代码将封装一个完整的组件,自定义底部弹窗菜单选择拍照或从手机相册选择,选完自动上传。
在这里插入图片描述

代码目录结构
在这里插入图片描述

utils/index.ets(工具类):


import fs from '@ohos.file.fs';
import bundleManager from '@ohos.bundle.bundleManager';
import abilityAccessCtrl, { Context, Permissions } from '@ohos.abilityAccessCtrl';
import common from '@ohos.app.ability.common'/*** 复制文件到缓存目录下* @param path :文件路径* @param context :Context* @returns Promise<string> 移动后文件路径*/
export async function copyFileToCache(path: string,context:Context): Promise<string> {try {let file =  fs.openSync(path, fs.OpenMode.READ_WRITE)if (file) {let fileDir: string = `${context.cacheDir}` //临时文件目录//时间戳生成随机文件名let newPath: string =  `${new Date().getTime()}_${path.split("/")[path.split("/").length-1]}`let targetPath: string = `${fileDir}/${newPath}`fs.copyFileSync(file.fd, targetPath)return  newPath}else {return ''}} catch (e) {return Promise.resolve('')}
}//校验应用是否授予权限
//@params permissions:权限名称数组
//@return permissionabilityAccessCtrl:权限名称
async function checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {let atManager = abilityAccessCtrl.createAtManager();let grantStatus: abilityAccessCtrl.GrantStatus = 0;// 获取应用程序的accessTokenIDlet tokenId: number = 0;try {let bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;tokenId = appInfo.accessTokenId;} catch (err) {console.error(`getBundleInfoForSelf failed, code is ${err.code}, message is ${err.message}`);}// 校验应用是否被授予权限try {grantStatus = await atManager.checkAccessToken(tokenId, permission);} catch (err) {console.error(`checkAccessToken failed, code is ${err.code}, message is ${err.message}`);}return grantStatus;
}//检查用户权限
//@params permissions:权限名称数组
export  async function checkPermissions(permissions: Permissions): Promise<boolean> {try {let grantStatus: abilityAccessCtrl.GrantStatus = await checkAccessToken(permissions);return grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED}catch (e) {return Promise.reject(e)}
}interface rejectObj {code: numbermessage: string
}
/*** 申请权限* @params context:AblitiyContext* @params permissions:权限名称数组* @returns  Promise<boolean>:是否授权成功*/
export async function applyPermission(context: common.UIAbilityContext, permissions: Array<Permissions>): Promise<boolean> {let atManager = abilityAccessCtrl.createAtManager();return new Promise((resolve: (res: boolean) => void, reject: (e: rejectObj) => void) => {atManager.requestPermissionsFromUser(context, permissions).then((data) => {let grantStatus: Array<number> = data.authResults;resolve(grantStatus.every(item => item === 0))}).catch((err: rejectObj) => {reject(err)})})
}

ImageUploadDialog.ets(图片上传弹窗菜单选择组件):

import picker from '@ohos.file.picker';
import { checkPermissions, applyPermission, copyFileToCache } from '../../utils/index'
import { request } from '@kit.BasicServicesKit';
import { Permissions } from '@ohos.abilityAccessCtrl';
import camera from '@ohos.multimedia.camera';
import camerapicker from '@ohos.multimedia.cameraPicker';
import { BusinessError } from '@ohos.base';
import { common } from '@kit.AbilityKit';@Extend(Text)
function custText() {.width('100%').height('48')    .fontColor('#39364D').textAlign(TextAlign.Center)
}@CustomDialog
export default struct ImageUploadDialog {dialogController: CustomDialogController@Prop uploadURL:string='';//上传接口地址private context = getContext(this) as common.UIAbilityContext; //UIAbilityContextprivate success:(res: request.TaskState[])=>void=()=>{}//上传成功回调private fail:(res: request.TaskState[])=>void=()=>{} //上传失败回调//检查权限async checkAppPermission(): Promise<boolean> {try {const READ_MEDIA_PERMISSION: Permissions = 'ohos.permission.READ_MEDIA' //媒体读取权限const WRITE_MEDIA_PERMISSION: Permissions = 'ohos.permission.WRITE_MEDIA' //媒体写入权限let permissionList: Permissions[] = []; //需要申请选项列表let readPermission = await checkPermissions(READ_MEDIA_PERMISSION)//检查是否有媒体读取权限!readPermission && permissionList.push(READ_MEDIA_PERMISSION)let writePermission = await checkPermissions(WRITE_MEDIA_PERMISSION)//检查是否有媒体写入权限!writePermission && permissionList.push(READ_MEDIA_PERMISSION)if (permissionList.length) {//申请权限let res: boolean = await applyPermission(this.context, permissionList)if (!res) {//用户未同意授权AlertDialog.show({title: "提示",message: "无权限读写用户外部存储中的媒体文件信息,请前往系统设置开启",alignment: DialogAlignment.Center,secondaryButton: {value: '关闭',action: () => {}}})}return res}return true}catch (e) {return Promise.reject(e)}}//开始上传图片 path:图片路径后缀(图片名称)async uploadImage(path: string) {console.log(path, 'path')let uri=`internal://cache/${path}` //上传图片全路径let uploadConfig: request.UploadConfig = {url:this.uploadURL,header:{},method: "POST",files: [{ filename: path, name: "file", uri, type: path.split('.')[path.split('.').length-1] }],data: [],};try {let uploadTask:request.UploadTask=await request.uploadFile(this.context, uploadConfig)//上传中回调uploadTask.on('progress', (size,total) => {console.log(size.toString(),total.toString(),'上传进度')})//上传完成回调uploadTask.on('complete', (taskStates: request.TaskState[]) => {console.info("upOnComplete complete taskState:" + JSON.stringify(taskStates));if(taskStates&&taskStates.length&& taskStates[0].responseCode===0){this.success&&this.success(taskStates)}})//上传失败回调uploadTask.on('fail', (taskStates: request.TaskState[]) => {console.info("upOnComplete fail taskState:" + JSON.stringify(taskStates));this.fail&&this.fail(taskStates)})}catch (e){console.log( JSON.stringify(e),'e')}}build() {Column() {//拍照Text('拍照').custText().onClick(async()=>{//检查是否有读写外部媒体权限let res: boolean = await this.checkAppPermission()//无权限返回if (!res) returntry {let pickerProfile: camerapicker.PickerProfile = {cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK};let pickerResult: camerapicker.PickerResult = await camerapicker.pick(this.context,[camerapicker.PickerMediaType.PHOTO, camerapicker.PickerMediaType.PHOTO], pickerProfile);if(pickerResult?.resultUri){//关闭弹窗this.dialogController.close()//复制图片到缓存目录(缓存目录才有读写权限)let filePath = await copyFileToCache(pickerResult.resultUri, this.context)if (filePath) {//上传头像并设置this.uploadImage(filePath)}}} catch (error) {let err = error as BusinessError;console.error(`the pick call failed. error code: ${err.code}`);}})Divider().color('#F7F9FA').width('100%').strokeWidth(1)//从手机相册选择Text('从手机相册选择').custText().onClick(async () => {//检查是否有读写外部媒体权限let res: boolean = await this.checkAppPermission()//无权限返回if (!res) return//关闭弹窗this.dialogController.close()//从相册选择let PhotoSelectOptions = new picker.PhotoSelectOptions();PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;PhotoSelectOptions.maxSelectNumber = 1;let photoPicker = new picker.PhotoViewPicker();photoPicker.select(PhotoSelectOptions).then(async (PhotoSelectResult) => {if (PhotoSelectResult.photoUris.length) {//复制图片到缓存目录(缓存目录才有读写权限)let filePath = await copyFileToCache(PhotoSelectResult.photoUris[0],this.context)if (filePath) {this.uploadImage(filePath)}}})})Button('取消', { type: ButtonType.Capsule }).backgroundColor('#F7F7F7').fontSize('16fp').fontColor('#333333').width('100%').margin({ top: '30' }).onClick(() => {this.dialogController.close()})}.width('100%').padding({ left: '16', top: '11', right: '16', bottom: '16' }).backgroundColor(Color.White).borderRadius({topLeft: '24',topRight: '24'})}
}

组件入参 说明:

uploadURL:上传接口url
success:(res: request.TaskState[])=>void 上传成功回调函数
fail:(res: request.TaskState[])=>void=()=>{} //上传失败回调

成功或失败回调参数说明

 request.TaskState[]: {path:string //图片在本地路径message:string //上传结果信息responseCode //上传结果状态码 0:成功,其他值失败}[]

从 request.TaskState字段描述可以看出request.uploadFile无法返回接口返回的数据,这也是最大的坑,期待官方解决,如果需要获取上传成功后返回的url,可以在设计个接口上传完再调用该接口获取图片url,如果像头像设置这种功能也可以把图片上传和头像设置整合成一个接口,上传完也即设置完成。

页面调用:

pages/Index

import ImageUploadDialog from '../components/ImageUploadDialog/ImageUploadDialog'
import { promptAction } from '@kit.ArkUI'@Entry
@Component
struct Index {@State dialogController: CustomDialogController | null = null //选择上传类型弹窗控制器aboutToAppear(): void {this.dialogController= new CustomDialogController({builder: ImageUploadDialog({uploadURL: 'http://xxxxxxxxx',//上传地址success:e=>{//上传成功回调console.log(JSON.stringify(e))promptAction.showToast({message:'上传成功'})},fail:e=>{//上传失败回调console.log(JSON.stringify(e))promptAction.showToast({message:'上传失败'})}}),alignment: DialogAlignment.Bottom,//弹窗居于底部customStyle: true,//自定义样式})}build() {Column(){Button('上传').onClick(()=>{this.dialogController?.open()})}.width('100%')}
}

最后不要忘记添加权限
三个:

  "ohos.permission.INTERNET":网访问权限"ohos.permission.READ_MEDIA":外部存储设备媒体读取权限"ohos.permission.WRITE_MEDIA":外部存储设备媒体写入权限

module.json5:

 //权限requestPermissions: [{"name": "ohos.permission.INTERNET",},{"name": "ohos.permission.READ_MEDIA","reason": "$string:reasonReadWriteMedia",//使用权限原因"usedScene": {"abilities": [//使用的该权限的EntryAbility名称数组"EntryAbility"],"when": "inuse"}},{"name": "ohos.permission.WRITE_MEDIA","reason": "$string:reasonReadWriteMedia","usedScene": {"abilities": ["EntryAbility"],"when": "inuse"}}]

entry\src\main\resources\base\element\string.json

{"string": [,{"name":"reasonReadWriteMedia","value": "上传头像"}]
}

效果:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

http://www.yayakq.cn/news/672945/

相关文章:

  • 郴州网站建设软件定制开发平台厦门推广平台较好的
  • php网站设置如何使用专业自助建站
  • 广州番禺营销型网站代运营报价
  • 怎么做口子推广网站百度关键词排名推广工具
  • 公司网站建设上海找谁企业展厅建筑设计
  • 息烽县住房和城乡建设局网站家里公网宽带做网站要备案么
  • 建一个com网站要多少钱汕头新导网络公司
  • 律师事务所网站建设方案wordpress文章选项
  • 做网站的windowlcd官方网站下载微信
  • 怎么开发一个网站英文版网站建设
  • 做网站公司长沙哪家好四川省工程项目建设投标发布网站
  • php培训机构企业做网站网吧服务员
  • 常州网站制作公司有哪些小程序开发费用明细怎么填
  • 建站开发工具门窗企业网站建设
  • 清河做网站哪里便宜电子商务网站建设可运用的技术
  • 自己开发购物网站中铁建设集团集采网站
  • 网站没有根目录图表统计类手机网站开发
  • 专做皮鞋销售网站装饰网站建设的方案
  • 网站建设技能考wordpress短代码参数值带
  • 做网站开始要注意什么百度网盘做存储网站
  • iis wordpress 多站点凡科建设网站
  • 网站怎么做文件上传本科自考需要考哪些科目
  • 如何做亚马逊备案的网站济南网站优化技术厂家
  • 网站建设与管理课程实训做网站建设需要
  • 建行手机网站专业seo优化推广
  • 餐饮网站建设有什么好处小网站从哪找的
  • 餐饮类网站模板社交软件开发费用
  • 潍坊网站建设多少钱视频制作教程自学
  • 网站平台做期货深圳光明
  • 网站搜索引擎怎样做网页传奇游戏平台排行