鸿蒙系统中实现保存pdf至本地

最近开发过程中遇到这样一个需求,需要将发票保存到本地,在网上看了一些案例,没有实现所需要的功能,并且都需要声明额外权限,于是我决定自己实现,在这里记录下我的实现过程。

pdf 展示方式

在下载之前首先是将 pdf 展示出来,ArkUI 中有一个 Web 组件,可以非常方便的实现这个功能。 Web 组件的用途就是用来展示和下载 web 内容,其能力由@ohos.web.webview 提供,因此也可以通过 url 来展示和下载 pdf。

ts 复制代码
Web({
  src: this.pdfUrl, // 加载网络PDF文档
  controller: this.controller,
}).domStorageAccess(true); // domStorageAccess 方法用于控制Web中对文档对象模型存储(DOM Storage API)的启用状态,若将其设置为 false,会影响到PDF文件在Web中的预览功能

实现思路

由于发票是由第三方平台所返回的,格式不固定,存在图片格式及已.pdf 结尾的 PDF 文件和无后缀的 PDF 文件,因此需要先判断文件类型,然后进行不同的处理。第二步下载文件到应用沙箱,第三部利用文件选择器将文件复制到公共目录下。

首先是通过url后缀判断文件类型

ts 复制代码
function getFileExtension(url: string): string {
  // 去除URL中的查询参数和锚点
  const cleanUrl = url.split('?')[0].split('#')[0];
  const filename = cleanUrl.substring(cleanUrl.lastIndexOf('/') + 1);
  // 提取扩展名(带点判断)
  const lastDotIndex = filename.lastIndexOf('.');
  if (lastDotIndex > 0) {
    // 确保点不在文件名开头
    return filename.substring(lastDotIndex).toLowerCase();
  }
  return '';
}

然后第二步,就是先将文件下载到沙箱中

ts 复制代码
 @State pdfUrl: string = '' // pdf地址
 ... // 省略其他代码 
 // 保存到本地沙箱
async saveToSandbox(){
      const sandboxDir = getContext().cacheDir;
    // 创建唯一文件名
      const fileExtension = this.getFileExtension(this.pdfUrl);
      const fileName = `invoice_${new Date().getTime()}${fileExtension ? fileExtension : '.pdf'}`;
      const fullPath = `${sandboxDir}/${fileName}`; // 直接拼接路径
      // 下载文件到沙箱中
      await this.downloadPDF(fullPath)
      // 保存到Download中
      this.copyToDownload(fileName,fullPath)
 }


 // 根据沙箱路径下载,这是一个异步过程
  async downloadPDF(fullPath: string): Promise<void> {
    this.controller.startDownload(this.pdfUrl);
    return new Promise((resolve, reject) => {
      try {
        this.delegate.onBeforeDownload((webDownloadItem: webview.WebDownloadItem) => {
          // 传入下载路径,并开始下载。
          webDownloadItem.start(fullPath);
        })
        this.delegate.onDownloadFailed((webDownloadItem: webview.WebDownloadItem) => {
          console.log("download failed guid: " + webDownloadItem.getGuid());
          ToastUtil.showToast('加载失败')
          reject()
        })
        this.delegate.onDownloadFinish((webDownloadItem: webview.WebDownloadItem) => {
          console.log("download finish guid: " + webDownloadItem.getGuid());
          resolve()
        })
        this.controller.setDownloadDelegate(this.delegate);
      } catch (error) {
        console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
        reject()
      }
    })
  }

最后,复制沙箱中的文件到本地Download目录中

ts 复制代码
 copyToDownload(fileName:string,fullPath:string){
    // 文件选择器配置
    const context = getContext(this) as common.UIAbilityContext;
    const documentViewPicker = new picker.DocumentViewPicker(context);
    const documentSaveOptions = new picker.DocumentSaveOptions();

    documentSaveOptions.newFileNames = [fileName]; // 设置默认文件名
    documentSaveOptions.pickerMode = picker.DocumentPickerMode.DOWNLOAD;

    // 打开文件选择器
    const uris = await documentViewPicker.save(documentSaveOptions);
    if (uris.length > 0) {
      const targetDir = new fileUri.FileUri(uris[0]).path;
      const targetUri = `${targetDir}/${fileName}`;
      // 复制到Download下
      const sourceStats = fs.statSync(fullPath);
      if (sourceStats.isFile()) {
        try {
          fs.copyFileSync(fullPath, targetUri);
          console.info(`文件已保存至:${targetUri}`);
          ToastUtil.showToast('下载成功:' + targetUri)
          // 删除临时文件
          fs.unlinkSync(fullPath);
        } catch (e) {
          console.error('文件复制失败' + e)
          ToastUtil.showToast('下载失败')
        }
      }
    }
 }

通过这种方式,就可以实现pdf的下载和保存,并且无需声明额外的权限。

相关推荐
weitingfu2 小时前
AI 游戏,为什么更适合鸿蒙?
人工智能·游戏·华为·ai·harmonyos
木斯佳2 小时前
鸿蒙开发入门指南:鸿蒙canvas实操——快速掌握自定义图表组件
harmonyos·自定义图表
光锥智能3 小时前
华为MateBook 14 鸿蒙版发布,体验全面升维
华为·harmonyos
UnicornDev3 小时前
【HarmonyOS 6】练习记录页面 UI 设计
ui·华为·harmonyos·arkts·鸿蒙
浮芷.3 小时前
生命科学数据视界防御:基于鸿蒙Flutter陀螺仪云台与三维体积光栅的视轴锁定架构
flutter·华为·架构·开源·harmonyos·鸿蒙
浮芷.3 小时前
微观搜打撤:基于鸿蒙flutter的内存快照算法的局内外状态隔离与高阶背包系统设计
算法·flutter·华为·开源·harmonyos·鸿蒙
浮芷.3 小时前
东方修仙模拟器:基于 鸿蒙Flutter 状态机与 CustomPainter 的境界跃升与天劫渲染架构
科技·flutter·华为·架构·开源·harmonyos·鸿蒙
民乐团扒谱机4 小时前
基于ArkTS与端云协同的鸿蒙智慧校园助手——项目报告(AIGC预警⚠️)
华为·aigc·harmonyos
互联网散修4 小时前
鸿蒙实战:运动健康类应用核心组件——语音播报模块设计与实现
华为·harmonyos·tts·语音播报
想你依然心痛4 小时前
HarmonyOS 6智能家居实战:基于悬浮导航与沉浸光感的“光影智家“全屋智能控制系统
华为·智能家居·harmonyos·智能控制·悬浮导航·沉浸光感