开发者的实用指南,掌握鸿蒙系统的压缩技术

在日常应用开发中,压缩与解压功能无处不在。无论是处理用户上传的图片,还是减少网络传输数据量,高效压缩技术都至关重要。本文将带你全面了解鸿蒙NEXT中的压缩与解压能力,并通过实际代码示例展示如何实现这些功能。

鸿蒙NEXT压缩技术概述

鸿蒙NEXT提供了多层次的压缩解决方案,从官方的@ohos.zlib模块到三方库支持,涵盖了多种压缩格式和场景需求。

支持的压缩格式包括:

压缩格式简介系统支持情况
ZIP普及率高,适用范围广,压缩速度较快ArkTS支持,可通过zlib实现
RAR相比ZIP提供更好的压缩率,但速度较慢三方库支持
7Z压缩率最大,但速度最慢三方库支持
GZIP使用gzip算法极大减少文件体积三方库支持
Brotli无损压缩算法,主要压缩Internet数据三方库支持
TAR简单的归档文件,仅是文件封装三方库支持

数据来源:

图片压缩实战

图片压缩是应用开发中最常见的需求之一,特别是在处理用户上传图片时。鸿蒙NEXT提供了强大的图片压缩能力,支持jpeg、webp、png等格式。

实现思路

  1. 拉起图库选择图片:使用photoAccessHelper.PhotoViewPicker创建图库选择器实例

  2. 读取图片数据:将图片数据读取到buffer,创建图片源实例

  3. 压缩处理:通过packing(质量压缩)和scale(尺寸压缩)方式进行压缩

  4. 保存图片:将压缩后的图片保存到图库

核心代码实现

typescript

async selectPhotoFromAlbum() {
  // 创建图库选项实例
  const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
  photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
  photoSelectOptions.maxSelectNumber = 1;
  
  // 创建图库选择器实例
  const photoViewPicker = new photoAccessHelper.PhotoViewPicker();
  
  // 选择图片
  photoViewPicker.select(photoSelectOptions).then((photoSelectResult) => {
    this.uris = photoSelectResult.photoUris;
    this.photoCount = this.uris.length;
    if (this.photoCount > 0) {
      const ALBUM_PATH: string = photoSelectResult.photoUris[0];
      // 读取选择图片的buffer
      const file = fs.openSync(ALBUM_PATH, fs.OpenMode.READ_ONLY);
      this.beforeCompressByteLength = fs.statSync(file.fd).size;
      fs.closeSync(file);
    }
  }).catch((err: BusinessError) => {
    hilog.error(0x0000, TAG, `PhotoViewPicker.select failed: error code: ${err.code}, message: ${err.message}.`);
  })
}

手动模式压缩图片:

typescript

manualCompression() {
  const ALBUM_PATH: string = this.uris[0];
  const file = fs.openSync(ALBUM_PATH, fs.OpenMode.READ_ONLY);
  let buffer = new ArrayBuffer(fs.statSync(file.fd).size);
  fs.readSync(file.fd, buffer);
  fs.closeSync(file);
  
  const decodingOptions: image.DecodingOptions = { editable: true };
  const imageSource: image.ImageSource = image.createImageSource(buffer);
  imageSource.createPixelMap(decodingOptions).then(async (originalPixelMap: image.PixelMap) => {
    // 使用scale对图片进行缩放,使用packing进行图片质量压缩
    // ... 压缩逻辑
  });
}

压缩模式选择

鸿蒙NEXT提供两种压缩模式:

  1. 自动模式:设置压缩目标大小,系统自动调整参数压缩到最接近但不超过目标大小

    • 优先压缩质量:先调整图片质量,不足时再调整尺寸

    • 优先压缩尺寸:先调整图片尺寸,同时可设置最低图片质量

  2. 手动模式:手动调整图片质量和尺寸参数进行精确控制

文件压缩与解压

除了图片压缩,鸿蒙NEXT还提供了完整的文件压缩与解压能力,支持对沙箱目录中的文件进行操作。

在Worker线程中压缩文件

为了避免阻塞主线程,建议在Worker子线程中执行压缩操作。

实现步骤

  1. 创建Worker线程文件

  2. 在主线程中创建Worker实例

  3. 通过postMessage()向Worker线程发送压缩参数

  4. 在Worker线程中使用zlib.compressFile接口压缩文件

  5. 返回压缩结果到主线程

核心代码

在主线程中:

typescript

// 创建Worker实例
let workerInstance: worker.ThreadWorker = new worker.ThreadWorker('@compressfile/ets/worker/Worker.ets');

// 向Worker线程发送消息
workerInstance.postMessage({
  pathDir: this.pathDir,
  compressZipPath: this.compressZipPath,
  beCompressFileDir: this.beCompressFileDir
});

在Worker.ets中:

typescript

const workerPort: ThreadWorkerGlobalScope = worker.workerPort;

workerPort.onmessage = (e: MessageEvents): void => {
  const pathDir: string = e.data.pathDir; // 沙箱目录
  const rawfileDirName: string = e.data.beCompressFileDir; // 被压缩文件目录名
  const outFilePath: string = `${pathDir}/${e.data.compressZipPath}`; // 压缩包输出路径
  
  // 检查并创建输出目录
  fs.access(outFileDir, (err: BusinessError, res: boolean) => {
    if (!res) {
      fs.mkdirSync(outFileDir);
    }
  });
  
  let options: zlib.Options = {
    level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION,
    memLevel: zlib.MemLevel.MEM_LEVEL_DEFAULT,
    strategy: zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY
  };
  
  // 压缩文件
  zlib.compressFile(`${pathDir}/${rawfileZipName}`, outFile, options, (errData: BusinessError) => {
    if (errData !== null) {
      logger.error(TAG, `compress failed with error message: ${errData.message}, error code: ${errData.code}`);
    } else {
      workerPort.postMessage(outFileDir);
    }
  })
}

文件解压

解压过程与压缩类似,使用zlib.decompressFile接口:

typescript

// 在Worker线程中解压文件
zlib.decompressFile(compressedFilePath, outFileDir, (errData: BusinessError) => {
  if (errData !== null) {
    logger.error(TAG, `decompress failed with error message: ${errData.message}, error code: ${errData.code}`);
  } else {
    workerPort.postMessage(outFileDir);
  }
})

不同路径下的文件处理

鸿蒙NEXT支持对不同资源路径下的文件进行压缩与解压:

  1. rawfile目录下的文件:通过resourceManager.getRawFileContent获取文件内容,然后拷贝到沙箱路径再进行压缩操作

  2. resfile目录下的文件:通过getContext().resourceDir获取路径,直接进行压缩操作

第三方压缩软件集成

除了使用鸿蒙原生的压缩能力,还可以集成第三方压缩软件。2345好压作为国内知名压缩软件,已完成鸿蒙电脑系统的全面适配升级,成为首批鸿蒙合作伙伴。

2345好压鸿蒙版的特点

  • 支持ZIP、7Z、RAR、GZ等39种压缩格式

  • 单个大文件压缩速度比Windows版本提升8倍以上

  • 多文件目录复杂场景下压缩速度提升至12倍

  • 深度融合鸿蒙分布式特性,支持多设备协同

性能优化建议

  1. 使用Worker线程:将压缩/解压操作放在Worker子线程中,避免阻塞主线程

  2. 合理选择压缩参数

    • 图片压缩时,根据需求选择优先质量还是优先尺寸

    • 设置合适的压缩级别,平衡压缩比和速度

  3. 内存管理:及时释放不再使用的压缩数据,避免内存泄漏

  4. 错误处理:完善的错误处理机制,确保压缩失败时应用仍能正常运行

常见问题与解决方案

问题一:zlib.decompress后需要释放资源吗?

解答:鸿蒙NEXT的zlib模块会自动管理内存,但如果在解压后出现异常,可能是上下文未完全清除,建议重启应用或确保每次解压使用新的实例。

问题二:压缩文件输出路径有特殊字符导致失败

解答:压缩文件输出路径不能包含特殊字符,请使用标准路径格式。

问题三:图片压缩达不到设定的目标大小

解答:检查参数配置是否合理,如scale每次缩小倍数设置较大但压缩目标大小设置很小时,可能出现此情况。可调整参数重新尝试。

总结

鸿蒙NEXT提供了全面而强大的压缩与解压能力,从图片优化到文件处理,涵盖了应用开发中的常见场景。通过本文的介绍,相信你已经对鸿蒙平台的压缩技术有了全面了解,并能够在实际项目中灵活运用这些能力。

无论是使用原生API还是第三方库,鸿蒙NEXT都能为你的应用提供高效、稳定的压缩解决方案,帮助优化应用性能,提升用户体验。