简介背景
在使用任何一个APP的时候, 登录之后总有个人信息功能, 个人信息里面我们需要使用好看的头像, 这样就需要用户自定义去获取本地图片上传使用.
为什么要封装上传图片代码
在鸿蒙开发中没有现成的上传图片的代码, 如果实现一个完整的代码, 需要使用上下文以及fs文件管理器将用户相册拷贝到应用沙箱中, 使用internel://cache这种路径进行获取图片路径. 这也是鸿蒙因为没有操作用户相册的权限导致的. 针对这种现象我封装了两种图片上传的代码.
使用HTTP方式上传图片
- 选择本地图片
pickerAvatar() {
const photoSelectOptions = new picker.PhotoSelectOptions()
photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE
photoSelectOptions.maxSelectNumber = 1
const photoViewPicker = new picker.PhotoViewPicker()
photoViewPicker.select(photoSelectOptions).then(result => {
console.log('mylog->photoViewPicker', JSON.stringify(result.photoUris))
// 1. 得到文件路径
this.URI = result.photoUris[0]
if (this.URI) {
this.uploadAvatar()
}
})
}
- 将图片拷贝到沙箱 -> 调用上传接口进行上传
uploadAvatar() {
try {
this.loading = true
// 2. 拷贝到应用沙箱中
const context = getContext(this) as common.UIAbilityContext;
const type = 'jpg'
const filenamepre = Date.now().toString()
const filename = filenamepre + '.' + type
const newFilePath = context.cacheDir + '/' + filename
console.log('mylog->URI:', this.URI)
fs.open(this.URI, fs.OpenMode.READ_ONLY).then(file => {
console.log('mylog->file:', file.fd)
fs.copyFile(file.fd, newFilePath).then(() => {
console.info('mylog->copy success', `internal://cache/` + filename)
// 3. 上传
const config: request.UploadConfig = {
url: '', // 这里是上传接口路径, 自行修改
method: 'POST',
header: {
'Accept': '*/*',
'Authorization': `Bearer ${this.user.token}`,
'Content-Type': 'multipart/form-data'
},
files: [{ name: 'file', uri: `internal://cache/` + filename, type: type, filename: filename }],
data: []
}
request.uploadFile(context, config).then(task => {
task.on('progress', (uploadedSize: number, totalSize: number) => {
console.log('mylog->size:', uploadedSize.toString(), '/', totalSize)
if (uploadedSize === totalSize) {
this.getUserInfo()
}
})
task.on('fail', (taskStates: Array<request.TaskState>) => {
console.log("mylog->upOnFail taskState:" + JSON.stringify(taskStates));
})
}, (err: BusinessError) => {
console.log('mylog-> upload err', JSON.stringify(err))
})
}).catch((err: BusinessError) => {
console.log('mylog->copyerr', JSON.stringify(err))
})
}).catch((err: BusinessError) => {
console.log('mylog->openerr', JSON.stringify(err))
})
} catch (err) {
console.log('mylog->err', JSON.stringify(err))
}
}
- 请求userInfo接口更行头像
getUserInfo() {
hdHttp.get<userInfoData>('userInfo').then(res => {
console.log('mylog->userInfo', JSON.stringify(res))
this.user.avatar = res.data.avatar ? res.data.avatar : ''
// AppStorage.Set('user', JSON.stringify(this.user))
authStore.setUser(this.user)
this.loading = false
promptAction.showToast({ message: '更新头像成功' })
})
}
最后在调用一下
Image()
.onClick(() => {
// 选择头像并上传this.pickerAvatar()
this.pickerAvatar()
})
使用Axios方式上传图片
- 拉起用户相册选择
let photoSelectOption = new picker.PhotoSelectOptions()
photoSelectOption.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE
photoSelectOption.maxSelectNumber = 1
let photoPicker = new picker.PhotoViewPicker()
const res: picker.PhotoSelectResult = await photoPicker.select(photoSelectOption)
this.uris = res.photoUris
- 将选择好的图片拷贝到沙箱中
const fileType = 'jpg'
const fileName = Date.now() + '.' + fileType
const cacheFilePath = this.context.cacheDir + '/' + fileName
const file = fs.openSync(this.uris[0], fs.OpenMode.READ_ONLY)
fs.copyFileSync(file.fd, cacheFilePath)
- 从沙箱缓存中获取图片路径
let formData = new FormData()
let files: Array<request.File> = [
{
filename: fileName,
type: fileType,
name: 'image',
uri: `internal://cache/${fileName}`
}
]
console.info('result---->', JSON.stringify(files[0].uri))
formData.append('img', files[0].uri, {
fileType: fileType,
fileName: fileName
})
- 调用上传接口将图片上传到服务器
axios<string, AxiosResponse<string>, FormData>({
url: 'https://hmajax.itheima.net/api/uploadimg',
method: 'POST',
data: formData,
headers: {
'Content-Type': 'multipart/form-data' // 文件上传
},
context: this.context,
// 上传进度, 可以使用页面组件显示在页面上, 方便用户查看上传进度
onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
let total = progressEvent.total ?? 0
this.progressValues = {
loaded: progressEvent.loaded,
total: progressEvent.total,
rate: Math.ceil(progressEvent.loaded / total * 100)
}
console.info('result---->progressEvent', JSON.stringify(this.progressValues))
}
})
.then((res: AxiosResponse<string>) => {
this.imagePath = JSON.parse(JSON.stringify(res.data)).data.url
console.info("result---->url: " + this.imagePath);
}).catch((err: AxiosError) => {
console.error("result---->error:" + JSON.stringify(err));
})
最后在调用一下
Image(this.imagePath ? this.imagePath : $r('app.media.icon'))
.width(70)
.height(70)
.borderRadius(35)
.border({ width: 1, color: Color.White })
.onClick(() => {
// 上传头像
this.getAvatar()
})