HarmonyOS 鸿蒙Next图片选择、压缩、文件上传

发布于 1周前 作者 zlyuanteng 来自 鸿蒙OS

HarmonyOS 鸿蒙Next图片选择、压缩、文件上传

/
* 图片选择和压缩工具类
*/
export class PhotoSelectUtil {
constructor() {
}

/

* 选择照片
* @returns 图片的url
/
static async selectPhoto(options?: photoAccessHelper.PhotoSelectOptions): Promise<Array<string>> {
try {
if (!options) {
//创建配置实例
options = new photoAccessHelper.PhotoSelectOptions()
}
//选择类型是图片
options.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE
//选择文件的最大个数
if (!options.maxSelectNumber) {
options.maxSelectNumber = 4
}
//支持拍照
if (!options.isPhotoTakingSupported) {
options.isPhotoTakingSupported = true
}
//已选中的图片集合
if (!options.preselectedUris) {
options.preselectedUris = []
}
//是否支持编辑图片
options.isEditSupported = false

//创建选择器
let photoPicker = new photoAccessHelper.PhotoViewPicker()
let result = await photoPicker.select(options)
if (result && result.photoUris && result.photoUris.length > 0) {
return result.photoUris
} else {
return []
}
} catch (err) {
logIMessage(‘选择照片异常:’ + JSON.stringify(err))
return []
}
}

/
* 压缩图片
* @param filePathOriginal 原始图片的uri 通过Picker选择器得到的uri
* @param filePathCompress 压缩图片的地址
* @param quality 压缩比例 0~100 百分比越小压缩程度越厉害
* @returns 压缩图片的地址 地址为空时代表压缩失败
*/
static async compressPhoto(filePathOriginal: string, mContext: common.UIAbilityContext,quality?: number,filePathCompress?:string): Promise<string> {
let fileOriginal: fileIo.File | undefined //原始文件
let fileTemporary: fileIo.File | undefined //临时存储文件,针对原始文件无法压缩的问题
let fileCompress: fileIo.File | undefined //压缩文件
let imageSource: image.ImageSource | undefined
let imagePacker: image.ImagePacker | undefined
try {
logIMessage(‘压缩图片’)
logIMessage(‘原始图片:’+filePathOriginal)
imagePacker = image.createImagePacker()
fileOriginal = fileIo.openSync(filePathOriginal)
let nameOriginal = fileOriginal.name
let type = nameOriginal.substring(nameOriginal.lastIndexOf(’.’) + 1) //文件类型
let sizeOriginal = fileIo.statSync(fileOriginal.fd).size / 1000 //原始文件大小
//目前压缩图片只支持jpeg、webp、png等格式,不是该格式的图片,需要先将原始图片保存到临时文件上,然后在使用临时文件进行压缩
if (type != ‘jpeg’ && type != ‘webp’ && type != ‘png’) {
type = ‘jpeg’
let filePathTemporary = mContext.cacheDir + “/” + ‘temporary.’+type
fileTemporary = fileIo.openSync(filePathTemporary, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
//将原始图片复制到临时文件上,方便后续的压缩处理
fileIo.copyFileSync(fileOriginal.fd, fileTemporary.fd)
logIMessage(‘临时图片:’ + filePathTemporary)
imageSource = image.createImageSource(fileTemporary.fd)
} else {
imageSource = image.createImageSource(fileOriginal.fd)
}
if(!filePathCompress){
filePathCompress = mContext.cacheDir + “/” + ‘compress.’ + type
}
if (fileIo.accessSync(filePathCompress)) {
fileIo.unlinkSync(filePathCompress)
}
fileCompress = fileIo.openSync(filePathCompress, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
if (!quality) {
quality = 50
let sizeUnit = 1000
if (sizeOriginal <= sizeUnit) {
quality = 70
}
if (sizeUnit < sizeOriginal && sizeOriginal <= sizeUnit * 10) {
quality = 30
}
if (sizeUnit * 10 < sizeOriginal) {
quality = 10
}
}
//开始压缩图片
await imagePacker.packToFile(imageSource, fileCompress.fd, { format: “image/” + type, quality: quality })
//释放资源
fileIo.closeSync(fileOriginal.fd)
fileIo.closeSync(fileCompress.fd)
if(fileIo.accessSync(filePathCompress)&&fileTemporary){
fileIo.closeSync(fileTemporary.fd)
}
logIMessage(‘压缩比例:’ + quality)
logIMessage(‘压缩图片:’+filePathCompress)
return filePathCompress
} catch (err) {
logIMessage(‘压缩图片异常:’ + JSON.stringify(err))
return ‘’
} finally {
logIMessage(‘图片压缩结束’)
}
}
}

界面调用

/
* 选择照片
/
showSelectPhoto() {
let options = new photoAccessHelper.PhotoSelectOptions();
options.maxSelectNumber = 1
// 调用选择图片的方法
PhotoSelectUtil.selectPhoto(options)
.then(async (data) => {//data为空则代表失败
if (data.length > 0) {
//压缩图片
PhotoSelectUtil.compressPhoto(data[0], mContext)
.then((filePath) => {
  //返回地址是压缩图片的path path为空则压缩失败,filePath可以在调用方法的时候传递进去
if (filePath.length > 0) {
this.uploadFile(filePath)//文件上传方法
}
})
}
})
}


 

/**
* 上传文件
* @param filePathOriginal 原始文件
/
static uploadFile(mContext: common.UIAbilityContext, filePathOriginal: string, onSuccess?: (file?: string) => void) {
if (TextUtil.isEmpty(filePathOriginal) && !fileIo.accessSync(filePathOriginal)) {
showToast(‘文件不存在,无法上传’)
return
}
printMessage(’
******************************************************* 开始上传文件 *******************************************************’)

let fileOriginal = fileIo.openSync(filePathOriginal)
let fileNameOriginal = fileOriginal.name
let type = fileNameOriginal.substring(fileNameOriginal.lastIndexOf(’.’) + 1)
let fileNameUpload=‘upload.’+type
let filePathUpload = mContext.cacheDir + “/” + fileNameUpload
let fileUpload= fileIo.openSync(filePathUpload, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
//将文件复制到缓存文件中,因为文件上传只能上传缓存里面的文件
if (filePathOriginal != filePathUpload) {
fileIo.copyFileSync(fileOriginal.fd, fileUpload.fd)
}
printMessage('原始文件: ’ + filePathOriginal)
printMessage(‘上传文件:’ + filePathUpload)
let realUri = “internal://cache/” + fileNameUpload
printMessage('realUri: ’ + realUri)
printMessage('type: ’ + type)
//设置文件参数
let files: Array<request.File> = [
{
filename: fileNameUpload,
name: ‘file’,
uri: realUri,
type: type
}
]
//设置请求头
let header = new Map<Object, string>();
header.set(‘Content-Type’, ‘multipart/form-data’)
//设置请求参数
let params: Array<request.RequestData> = []
let phoneDeviceId = AppCacheUtil.getPhoneDeviceId()
params.push({ name: ‘uuid’, value: phoneDeviceId })
params.push({ name: ‘platform’, value: ‘android’ })

let uploadConfig: request.UploadConfig = {
url: ‘https//xxx/xxx’,
header: header,
method: ‘POST’,
files: files,
data: params
}
// 将本地应用文件上传至网络服务器
try {
request.uploadFile(mContext, uploadConfig)
.then((uploadTask: request.UploadTask) => {
printMessage(‘订阅各种事件’)
let uploadFileComplete = (taskStates: Array<request.TaskState>) => {
printMessage(‘文件上传结束,’ + JSON.stringify(taskStates))
}
let uploadFileProgress = (uploadedSize: number, totalSize: number) => {
printMessage(文件上传进度 uploadedSize: ${uploadedSize} totalSize: ${totalSize})
}
let headerReceive=(header: object) => {
printMessage(‘body:’ + JSON.stringify(header))
  //解析请求参数
let result = JSON.parse(((header as Record<string, string>)[‘body’] as string)) as ResultEntity
printMessage('文件地址: ’ + result.data?.file)
if (onSuccess != null) {
onSuccess(result.data?.file)
}
//上传完成,取消订阅
uploadTask.off(‘complete’,uploadFileComplete)
uploadTask.off(‘progress’, uploadFileProgress)
uploadTask.off(‘fail’,uploadFileComplete)
uploadTask.off(‘headerReceive’,headerReceive)
}
uploadTask.on(‘complete’, uploadFileComplete)
uploadTask.on(‘progress’, uploadFileProgress)
uploadTask.on(‘fail’, uploadFileComplete)
uploadTask.on(‘headerReceive’, headerReceive)
})
.catch((err: BusinessError) => {
printMessage(文件上传失败, code is ${err.code}, message is ${err.message});
})
.finally(() => {
printMessage(‘finally’)
//释放资源
fileIo.closeSync(fileOriginal.fd)
fileIo.closeSync(fileUpload.fd)
//清理掉临时存放在缓存的上传文件
if (fileIo.accessSync(filePathUpload)&&filePathOriginal!=filePathUpload) {
fileIo.unlinkSync(filePathUpload)
}
LoadingDialog.hideDialog()
})
} catch (error) {
let err: BusinessError = error as BusinessError;
printMessage(文件上传异常, code is ${err.code}, message is ${err.message});
}
}

总结:

选择图片或者拍照  调用方法 传递参数  参数可以默认不传递  默认是选择4张图片  选中完成之后返回选择图片的url地址集合

压缩图片:

   1、先判断图片的格式是否支持压缩,如果不支持创建临时图片用来存储要压缩的图片数据

   2、使用原始图片或者临时图片 生成ImageSourced对象实例

   3、创建压缩图片文件  调用openSync获取file对象  调用该方法相当于提前创建压缩图片的文件

   4、创建imagePacker对象实例

   5、创建PackingOption  参数:format即文件格式  quality:图片质量百分比,百分比越高压缩程度越小

   6、使用imagePacker实例  调用packToFile方法进行图片压缩  传递参数:原始图片或者临时图片生成的ImageSourced、压缩图片文件的.fd、PackingOption

   7、释放资源

上传文件:

1、因为文件上传只支持上传缓存内的文件,所以需要先将要上传的原始文件复制到缓存文件上

2、设置文件参数  fileName:缓存文件的名字、  name:默认是file(和后台云端对接即可)  url: 'internal://cache/+缓存文件名字  type:缓存文件的后缀名

3、设置请求头默认即可

4、设置表单参数,和云端对接 格式按照demo写就行

5、设置uploadConfig   参数: url:接口地址 , header:请求头  ,method:请求方式默认post , files:文件参数,data:表单参数

6、调用request.uploadFile(mContext, uploadConfig)方法  在成功回调里面 订阅各种事件

    complete、fail事件 代表方法执行停止  或者结束或者异常

    progress事件  上传进度

    headerReceive 事件  请求头和返回结果  从返回数据解析云端的返回结果

1 回复

HarmonyOS 鸿蒙Next图片选择、压缩、文件上传功能实现如下:

  1. 图片选择:使用系统提供的Picker组件,如PhotoViewPicker,通过配置选项实现图片选择。支持单选或多选,并可根据需求设置MIME类型等。

  2. 图片压缩:HarmonyOS支持多种图片压缩方式,如通过调整图片质量和尺寸进行压缩。可使用系统API或第三方库实现,确保图片大小符合上传要求。

  3. 文件上传:上传前需将图片保存到应用缓存目录(cacheDir),因为鸿蒙系统仅支持上传缓存目录下的文件。使用request.uploadFile接口上传图片,可设置请求头、请求方法等参数。

如果问题依旧没法解决请加我微信,我的微信是itying888。

回到顶部