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

【HarmonyOS NEXT】实现网络图片保存到手机相册

【问题描述】
给定一个网络图片的地址,实现将图片保存到手机相册

【API】

phAccessHelper.showAssetsCreationDialog

【官方文档】
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-photoaccesshelper-V5#showassetscreationdialog12

【完整代码】

import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import util from '@ohos.util';
import { fileUri } from '@kit.CoreFileKit';
import fs, { ReadOptions } from '@ohos.file.fs';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { dataSharePredicates } from '@kit.ArkData';
import { promptAction } from '@kit.ArkUI';

@Entry
@Component
struct SaveAlbum {
  @State message: string = 'Hello World';
  url1: string = "https://img20.360buyimg.com/img/jfs/t1/241153/31/4968/64736/65e53e56Fd3868b6e/b595d41ca8447ea4.jpg";
  url2: string =
    "https://upfile-drcn.platform.hicloud.com/ptTJ5B1eJ6k-d45UmOTF0Q.FYlVoBLGO3P9jZfjPUtqh2Cry9mQBzJButWu-okMhg2Xsd4zaoBTVAAsA08DPk1Vn7VFa1Mpl1Dp112CNKhEBjd4a9kP2NCKrQUpgq0HP_E3uqofnQ.6099200.png";

  build() {
    Column({ space: 30 }) {
      Text('保存到相册').fontSize(30)
      Column() {
        Text(this.url1)
        Button("保存").onClick(() => {
          this.downloadAndSave(this.url1)
        })
      }.margin({ top: 15, bottom: 15 })

      Column() {
        Text(this.url2)
        Button("保存").onClick(() => {
          this.downloadAndSave(this.url2);
        })
      }.margin({ top: 15, bottom: 15 })
    }.justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).height('100%').width('100%')
  }

  downloadAndSave(url: string) {
    const arr = url.split('.')
    const type = arr[arr.length -1]
    httpDownload(url, type).then((result: DownloadResult) => {
      if (result.isSuccess) {
        promptAction.showToast({ message: "下载成功" })
      } else {
        console.error("失败:" + result.msg);
        promptAction.showToast({ message: "下载失败❌,请查看日志" })
      }
    })
  }
}

interface DownloadResult {
  isSuccess: boolean,
  msg: string
}

async function httpDownload(imgUrl: string, imgType: string): Promise<DownloadResult> {
  return new Promise((resolve, reject) => {
    http.createHttp().request(imgUrl, async (error: BusinessError, data: http.HttpResponse) => { // 下载失败
      if (error) {
        return resolve({ isSuccess: false, msg: "下载失败" });
      } // 数据格式不正确
      if ((data.result instanceof ArrayBuffer) == false) {
        return resolve({ isSuccess: false, msg: "图片保存失败:数据流不支持" });
      } // 保存到Cache目录下
      let imageBuffer: ArrayBuffer = data.result as ArrayBuffer;
      const newFileName = util.generateRandomUUID() + "." + imgType;
      const newFilePath = getContext().cacheDir + "/" + newFileName;
      const newFileUri = fileUri.getUriFromPath(newFilePath);
      let file: fs.File = await fs.open(newFileUri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
      await fs.write(file.fd, imageBuffer);
      await fs.close(file);
      console.info("文件路径:" + newFileUri); // 保存成功 // resultData.status = 3; // return resolve(resultData);
      saveImageToAsset(newFileUri, imgType).then(() => { // 保存成功
        return resolve({ isSuccess: true, msg: "保存成功" });
      }).catch((error: Error) => { // 保存失败
        return resolve({ isSuccess: false, msg: "保存失败:" + error.message });
      });
    });
  })
}

async function saveImageToAsset(uri: string, nameExtension: string): Promise<void> {
  console.info('ShowAssetsCreationDialogDemo: ' + uri);
  try {
    let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(getContext()); // 获取需要保存到媒体库的位于应用沙箱的图片/视频uri
    let srcFileUris: Array<string> = [uri];
    let photoCreationConfigs: Array<photoAccessHelper.PhotoCreationConfig> = [{
      title: 'test2', // 可选
      fileNameExtension: nameExtension,
      photoType: photoAccessHelper.PhotoType.IMAGE, // 可选,支持:普通图片、动态图片
      subtype: photoAccessHelper.PhotoSubtype.DEFAULT,
    }];
    let desFileUris: Array<string> = await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
    console.info('showAssetsCreationDialog success, data is ' + desFileUris);
    if (desFileUris.length == 0) { // 用户拒绝保存
      throw (new Error("用户拒绝保存"))
    }
    await createAssetByIo(uri, desFileUris[0]);
    return Promise.resolve();
  } catch (err) {
    console.error('showAssetsCreationDialog failed, errCode is ' + err.code + ', errMsg is ' + err.message);
    return Promise.reject(err);
  }
}

let context = getContext(this);
const createAssetByIo = async (sourceFilePath: string, targetFilePath: string) => {
  try {
    console.log(`context.fileDir ===> ${context.filesDir}`)
    let srcFile: fs.File = fs.openSync(sourceFilePath, fs.OpenMode.READ_ONLY);
    let targetFile: fs.File = await fs.open(targetFilePath, fs.OpenMode.READ_WRITE);
    let bufSize = 14096;
    let readSize = 0;
    let buf = new ArrayBuffer(bufSize);
    let readOptions: ReadOptions = { offset: readSize, length: bufSize };
    let readLen = fs.readSync(srcFile.fd, buf, readOptions);
    while (readLen > 0) {
      readSize += readLen;
      fs.writeSync(targetFile.fd, buf, { length: readLen });
      readOptions.offset = readSize;
      readLen = fs.readSync(srcFile.fd, buf, readOptions);
    }
    fs.closeSync(srcFile);
    fs.closeSync(targetFile);
  } catch (error) {
    console.error(`createAssetByIo :: error , msg is ${error} `);
  }
}

【效果图】

【其它问题】
关于授权窗,没显示图片缩略图的问题,官方有答复是下载最新版本的IDE
在这里插入图片描述


http://www.kler.cn/news/307492.html

相关文章:

  • node.js+Koa框架+MySQL实现注册登录
  • Golang | Leetcode Golang题解之第412题Fizz Buzz
  • [创业之路-147] :国际标准化产品的研发与非标自动化产品研发的比较?
  • Linux进阶 修改文件权限
  • 2024年9月HarmonyOS鸿蒙应用开发者高级认证全新题库(覆盖99%考题)
  • 微软Copilot将集成到新加坡的法律科技平台中
  • electron-updater实现electron全量版本更新
  • 营收同比大增215%,联想x86服务器夯实市场前三
  • Docker和K8S
  • SOCKS5代理验证参数详解:如何确保代理的可靠性
  • LabVIEW中AVI帧转图像数据
  • Python:抓取 Bilibili(B站)评论、弹幕、字幕等
  • Android中的四大组件
  • 使用 Java 初步搭建简单Spring 项目框架:
  • C++设计模式——Prototype Pattern原型模式
  • 本科生如何学习机器学习
  • 如何通过编程工具提升工作效率
  • Vue3项目开发——新闻发布管理系统(七)
  • vue2——使用Element-UI实现可搜索的树形结构
  • JSON处理工具类
  • CUDA及GPU学习资源汇总
  • 强化学习Reinforcement Learning|Q-Learning|SARSA|DQN以及改进算法
  • 无人机PX4飞控ROS应用层开发:MAVROS 功能包介绍与飞控消息汇总(一)
  • 如何在Flask中处理表单数据
  • ISP住宅网络的特点是什么
  • 深度学习--------------序列模型
  • java技术栈介绍
  • 探索Web3前沿:革新性算力共享平台,重塑数字资源利用新时代
  • Spring Boot-API网关问题
  • ★ C++进阶篇 ★ 多态