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

鸿蒙OSS文件(视频/图片)压缩上传组件-能够增删改查

 一、鸿蒙实现处理-压缩上传整体代码处理逻辑

  1. 转沙箱
  2. 压缩
  3. 获取凭证并上传文件
    1. 文件准备(拿到文件流)
    2. 获取上传凭证(调接口1拿到file_name和upload_url)
    3. 执行文件上传(向阶段2拿到的upload_url上传文件)
    4. 更新列表数据 (将阶段2获取到的file_name更新进去,最后提交表单时传参)
  4. 提交表单
 // 处理视频/图片(转沙箱、压缩、调接口获取url、上传到OSS)// index不是undefined时:修改async handleFile(messageInfo: MessageInfo, index?: number) {loadingInstance.show()if (this.videoFlag) {// 1视频处理// 1)转沙箱const file = uriToSandBox(messageInfo.sourceFilePath);// 2)压缩const fileUri = await this.videoToCompress(file.fileUri).catch(() => {loadingInstance.hide()showToast('视频压缩失败');});let stat = fs.statSync(fileUri as string);if (stat.size / 1024 / 1024 > 50) {loadingInstance.hide()showToast('请拍摄50M以内的视频');return;}// 3)获取上传凭证并上传fileUri && this.fileUpload(fileUri, messageInfo, index)} else {// 2图片处理const file = uriToSandBox(messageInfo.sourceFilePath);// 1)转沙箱并压缩const fileUri = await this.transferFile(messageInfo.sourceFilePath).catch(() => {loadingInstance.hide()});// 2)获取上传凭证并上传fileUri && this.fileUpload(fileUri, messageInfo, index)}}

二、压缩部分

实现思路:

图片压缩

packing二分方式循环压缩

视频压缩

三种方案

代码:

// 优先压缩图片质量
async qualityPriorityCompress(sourcePixelMap: image.PixelMap, maxCompressedImageSize: number) {let compressedImageData: ArrayBuffer =await this.packing(sourcePixelMap, IMAGE_QUALITY_ZERO, this.afterCompressFmt);// 先判断图片质量参数设置最低0能否满足目标大小。如果能满足目标大小,则直接使用packing二分图片质量。如果不满足,则质量参数固定为0,进行scale尺寸压缩if (compressedImageData.byteLength <= maxCompressedImageSize * BYTE_CONVERSION) {// 满足目标大小,直接使用packing二分await this.packingImage(sourcePixelMap, compressedImageData, maxCompressedImageSize * BYTE_CONVERSION);} else {// 不满足目标大小,质量参数设置为0,再进行scale尺寸压缩await this.scalePriorityCompress(sourcePixelMap, maxCompressedImageSize, IMAGE_QUALITY_ZERO);}// 更新显示压缩后的图片格式this.showCompressFormat = this.afterCompressFmt;
}// packing二分方式循环压缩
async packingImage(sourcePixelMap: image.PixelMap, compressedImageData: ArrayBuffer, maxCompressedImageByte: number) {let imageQuality: number = 0;const DICHOTOMY_ACCURACY = this.minBisectUnit;// 图片质量参数范围为0-100,这里以minBisectUnit为最小二分单位创建用于packing二分图片质量参数的数组。const packingArray: number[] = [];// 性能知识点: 如果对图片压缩质量要求不高,建议调高minBisectUnit(对应‘packing最小二分单位’),减少循环,提升packing压缩性能。for (let i = 0; i <= 100; i += DICHOTOMY_ACCURACY) {packingArray.push(i);}let left = 0; // 定义二分搜索范围的左边界let right = packingArray.length - 1; // 定义二分搜索范围的右边界const AFTER_COMPRESS_FMT = this.afterCompressFmt;// 二分压缩图片while (left <= right) {const mid = Math.floor((left + right) / 2); // 定义二分搜索范围的中间位置imageQuality = packingArray[mid]; // 获取二分中间位置的图片质量值// 根据传入的图片质量参数进行packing压缩,返回压缩后的图片文件流数据。compressedImageData = await this.packing(sourcePixelMap, imageQuality, AFTER_COMPRESS_FMT);// 判断查找一个尽可能接近但不超过压缩目标的压缩大小if (compressedImageData.byteLength <= maxCompressedImageByte) {// 二分目标值在右半边,继续在更高的图片质量参数(即mid + 1)中搜索left = mid + 1;// 判断mid是否已经二分到最后,如果二分完了,退出if (mid === packingArray.length - 1) {break;}// 获取下一次二分的图片质量参数(mid+1)压缩的图片文件流数据compressedImageData = await this.packing(sourcePixelMap, packingArray[mid + 1], AFTER_COMPRESS_FMT);// 判断用下一次图片质量参数(mid+1)压缩的图片大小是否大于指定图片的压缩目标大小。如果大于,说明当前图片质量参数(mid)压缩出来的// 图片大小最接近指定图片的压缩目标大小。传入当前图片质量参数mid,得到最终目标图片压缩数据。if (compressedImageData.byteLength > maxCompressedImageByte) {compressedImageData = await this.packing(sourcePixelMap, packingArray[mid], AFTER_COMPRESS_FMT);break;}} else {// 目标值不在当前范围的右半部分,将搜索范围的右边界向左移动,以缩小搜索范围并继续在下一次迭代中查找左半部分。right = mid - 1;}}// ...
}

三、OSS上传文件部分

方案图:

 

 代码:

鸿蒙环境服务端签名直传_对象存储(OSS)-阿里云帮助中心

 // 获取上传凭证并上传// index不是undefined时:修改private fileUpload = async (fileUrl: string, messageInfo: MessageInfo, index?: number) => {let fileInfo: fs.File | null = null;try {// 阶段1:文件准备fileInfo = await fs.open(fileUrl, fs.OpenMode.READ_ONLY);const fileStat = await fs.stat(fileInfo.fd);const fileData = new ArrayBuffer(fileStat.size);await fs.read(fileInfo.fd, fileData);// 阶段2:获取上传凭证(调接口1拿到file_name和upload_url)const fileType = this.videoFlag ? 'mp4' : 'jpg';const uploadInfo = await this.getUploadCredentials(fileType);// 阶段3:执行文件上传(向阶段2拿到的upload_url上传文件)await this.uploadFileToOSS(uploadInfo.upload_url, fileData, fileStat.size)// 阶段4:更新列表数据 (将阶段2获取到的file_name更新进去,最后提交表单时传参)this.updateMediaLists(uploadInfo.file_name, messageInfo, index);return true;} catch (error) {showToast('文件上传失败,请重新上传')return false;} finally {// 确保资源释放if (fileInfo?.fd) {await fs.close(fileInfo.fd);}loadingInstance.hide();}};

相关文章:

  • Harbor2.0仓库镜像清理策略
  • 考研系列-计算机组成原理第六章、总线
  • Servlet (简单的servlet的hello world程序)
  • HK1RBOX K8 RK3528 Via浏览器_插件_央视频的组合验证(失败)
  • AVFormatContext 再分析
  • python+adafruit_pca9685 测试舵机存储当前角度
  • 中国区域250米归一化植被指数数据集(2000-2023)
  • 数据库3,
  • 前端Ui设计工具
  • BP 算法探秘 :神经网络的幕后引擎
  • 单值映射、多值映射
  • 单点登录(双token)的简单总结
  • C++ 类与对象(中)—— 默认成员函数与运算符重载的深度解析:构造函数,析构函数,拷贝构造函数,赋值运算符重载,普通取地址重载,const取地址重载
  • Java使用微信云服务HTTP API操作微信云开发数据库
  • WebGIS面试题目整合资料
  • 《TVM模式匹配实战:从DFPatternNode到DFPattern的高级用法》
  • PPIO X OWL:一键开启任务自动化的高效革命
  • Codeforces Round 1021 (Div. 2) D. Baggage Claim(建图)
  • PLC在仪表控制系统中的应用
  • 代码随想录算法训练营第60期第二十天打卡
  • 十四届全国人大常委会第十五次会议在京举行,审议民营经济促进法草案等
  • 涉李小龙形象商标被判定无效,真功夫:暂无更换计划
  • 泰山景区管委会:未经审核同意不得擅自举办竞速类登山活动
  • 弘扬 “上海精神”,上合组织政党论坛聚焦政党责任与使命
  • 现场|贝聿铭上海大展:回到他建筑梦的初始之地
  • 瑞士外长答澎湃:瑞中都愿升级自贸协定,关税战没有任何好处