六、【鸿蒙 NEXT】如何实现图片下载,并保存本地

230 阅读3分钟

 前言:

可能很多应用都会涉及网络图片的下载,本节将介绍下,如何在纯鸿蒙中实现图片的下载,并将图片保存到本地目录,或者直接保存到相册中。

本节主要涉及以下几点:

1、下载图片流

2、将图片流转为Image组件能展示的对象PixelMap

3、将图片保存到本地路径,路径由用户选择

4、直接将图片保存到相册

一、下载图片流

import { http } from '@kit.NetworkKit'

export class DownloadUtil {
  // 根据url下载图片,获取的是ArrayBuffer对象
  public static async downLoadPic(url:string):Promise<ArrayBuffer|null> {
    let data = await http.createHttp().request(url);
    if (data.result instanceof ArrayBuffer) {
      let imageData:ArrayBuffer = data.result
      return imageData;
    }
    return null;
  }
}

二、将图片的ArrayBuffer对象转换为Image组件能展示的PixelMap对象 。

Image组件本身是能直接接收url的,此处之所以要转换为PixelMap对象是考虑到可能有些应用由于性能问题,会提前开启线程去做图片的预加载,此时就会涉及到将图片流转换为PixelMap对象。

import { image } from '@kit.ImageKit';
  
// 将ArrayBuffer转换为PixelMap对象,该对象可以直接传给Image组件使用
  public static async arrayBufToPixelMap(buf:ArrayBuffer):Promise<PixelMap> {
    let imgSource:image.ImageSource = image.createImageSource(buf);
    let result:PixelMap = await imgSource.createPixelMap();
    return result;
  }

三、将图片直接保存到本地,且路径由用户自己选择。

关键代码如下,保存的图片可以在"文件管理"的app中查找。 

import fs from '@ohos.file.fs'
  
// 将图片流保存到本地,路径由用户选择
  public static saveToLocal(imageData:ArrayBuffer, contentType:string) {
    let photoSaveOption = new picker.AudioSaveOptions();
    let photoViewPicker = new picker.AudioViewPicker();
    photoSaveOption.newFileNames = [new Date().getTime() + '.jpg']
    if (contentType === 'video') {
      photoSaveOption.newFileNames = [new Date().getTime() + '.mp4']
    }
    // 此处会拉起系统的文件路径选择界面
    photoViewPicker.save(photoSaveOption).then(async (photoSaveResult) => {
      let uri = photoSaveResult[0];
      let file: fs.File = null!;
      try {
        file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
        await fs.write(file.fd, imageData);
      } finally {
        await fs.close(file.fd);
      }
    })
  }

四、直接将图片流保存到本地相册

因为访问相册需要额外申请一个系统权限,申请该权限有比较多的限制 。因此我们可以使用SaveButton()组件来实现保存到相册,点击该组件可以有10s的临时权限去操作相册。

import { photoAccessHelper } from '@kit.MediaLibraryKit';

// 将图片流保存到相册
  public static async savePicToGallery(context:common.UIAbilityContext, buf:ArrayBuffer) {
    let helper = photoAccessHelper.getPhotoAccessHelper(context);
    let file: fs.File = null!;
    try {
      // 当点击SaveButton组件后10秒内通过createAsset接口创建图片文件,10秒后createAsset权限收回
      let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE,'jpg');
      file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
      await fs.write(file.fd, buf);
    } finally {
      await fs.close(file.fd);
    }
  }

完整的代码示例如下:

DownloadUtil类

import { http } from '@kit.NetworkKit'
import { image } from '@kit.ImageKit';
import { picker } from '@kit.CoreFileKit';
import fs from '@ohos.file.fs'
import {common} from '@kit.AbilityKit'
import { photoAccessHelper } from '@kit.MediaLibraryKit';

export class DownloadUtil {
  // 根据url下载图片,获取的是ArrayBuffer对象
  public static async downLoadPic(url:string):Promise<ArrayBuffer|null> {
    let data = await http.createHttp().request(url);
    if (data.result instanceof ArrayBuffer) {
      let imageData:ArrayBuffer = data.result
      return imageData;
    }
    return null;
  }

  // 将ArrayBuffer转换为PixelMap对象,该对象可以直接传给Image组件使用
  public static async arrayBufToPixelMap(buf:ArrayBuffer):Promise<PixelMap> {
    let imgSource:image.ImageSource = image.createImageSource(buf);
    let result:PixelMap = await imgSource.createPixelMap();
    return result;
  }

  // 将图片流保存到本地,路径由用户选择
  public static saveToLocal(imageData:ArrayBuffer, contentType:string) {
    let photoSaveOption = new picker.AudioSaveOptions();
    let photoViewPicker = new picker.AudioViewPicker();
    photoSaveOption.newFileNames = [new Date().getTime() + '.jpg']
    if (contentType === 'video') {
      photoSaveOption.newFileNames = [new Date().getTime() + '.mp4']
    }
    // 此处会拉起系统的文件路径选择界面
    photoViewPicker.save(photoSaveOption).then(async (photoSaveResult) => {
      let uri = photoSaveResult[0];
      let file: fs.File = null!;
      try {
        file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
        await fs.write(file.fd, imageData);
      } finally {
        await fs.close(file.fd);
      }
    })
  }

  // 将图片流保存到相册
  public static async savePicToGallery(context:common.UIAbilityContext, buf:ArrayBuffer) {
    let helper = photoAccessHelper.getPhotoAccessHelper(context);
    let file: fs.File = null!;
    try {
      // 当点击SaveButton组件后10秒内通过createAsset接口创建图片文件,10秒后createAsset权限收回
      let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE,'jpg');
      file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
      await fs.write(file.fd, buf);
    } finally {
      await fs.close(file.fd);
    }
  }
}

页面:

import { DownloadUtil } from '../250226/DownloadUtil'
import { common } from '@kit.AbilityKit'

@Entry
@Component
struct Index {
  @State pixelMap:PixelMap|null = null
  // 此处可以换成可下载的图片
  url:string = 'http://xxxx.xxx.xxx'

  build() {
    Column(){
      Text('111')
      Image(this.pixelMap)
      Button('保存用户选择路径').onClick(async () => {
        let buf = await DownloadUtil.downLoadPic(this.url);
        if (buf) {
          DownloadUtil.saveToLocal(buf, 'image');
        }
      })
      SaveButton()
        .onClick(async (event:ClickEvent, result: SaveButtonOnClickResult) => {
          if (result === SaveButtonOnClickResult.SUCCESS) {
            let buf = await DownloadUtil.downLoadPic(this.url);
            if (buf) {
              let context = getContext(this) as common.UIAbilityContext
              DownloadUtil.savePicToGallery(context, buf);
            }
          }
        })
    }
  }
}