You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取expo-sharing下载状态 检测PDF文件是否下载完成

Expo-Sharing实现PDF下载状态同步方案

问题核心原因

expo-sharing本身只负责调起系统级的分享/文件保存弹窗,如果你直接把远程PDF URL传入分享方法,整个下载流程是由系统服务接管的,前端层拿不到下载进度、操作结果的回调,自然无法判断是否下载完成、用户是否取消操作。

实现思路

别直接把远程地址丢给分享组件,先用expo-file-system自主管控PDF的全量下载流程,等文件完整下载到本地临时目录后,再把本地文件路径传给expo-sharing调起操作,三类状态全程自己维护,完全可控。

具体实现步骤

  • 安装必需依赖
    执行以下命令安装配套的文件系统库:
    npx expo install expo-file-system expo-sharing
    
  • 定义统一状态标识
    先在业务代码里固定三类状态值,方便UI层同步对应提示:
    const PDF_STATUS = {
      DOWNLOADING: 'downloading', // 下载中
      CANCELED: 'canceled', // 已取消
      COMPLETED: 'completed' // 已完成
    }
    
  • 编写带状态管控的下载分享逻辑
    核心逻辑分为三段:创建可控下载任务标记下载中状态、监听下载完成事件、调起分享后根据返回结果标记取消/完成状态,参考代码如下:
    import * as FileSystem from 'expo-file-system';
    import * as Sharing from 'expo-sharing';
    
    const downloadAndSharePDF = async (remotePdfUrl, fileName) => {
      // 初始化状态为下载中,UI可同步展示加载提示、进度条
      let currentStatus = PDF_STATUS.DOWNLOADING;
      // 生成本地临时文件存储路径
      const localUri = `${FileSystem.cacheDirectory}${fileName}.pdf`;
    
      try {
        // 创建可中断的下载任务,可自行监听下载进度做进度展示
        const downloadResumable = FileSystem.createDownloadResumable(
          remotePdfUrl,
          localUri,
          {},
          (downloadProgress) => {
            const progress = downloadProgress.totalBytesWritten / downloadProgress.totalBytesExpectedToWrite;
            // 这里可以同步更新下载进度到UI
            console.log(`下载进度:${(progress * 100).toFixed(0)}%`);
          }
        );
    
        // 要支持下载中途用户点取消,就把downloadResumable存在ref里
        // 用户点取消按钮时调用 downloadResumable.cancelAsync() 即可中断下载,同时把状态置为CANCELED
    
        // 等待文件下载完成
        const downloadResult = await downloadResumable.downloadAsync();
        if (!downloadResult?.uri) throw new Error('文件下载失败');
    
        // 校验本地文件是否存在、大小是否正常,避免下载到损坏文件
        const fileInfo = await FileSystem.getInfoAsync(downloadResult.uri);
        if (!fileInfo.exists || fileInfo.size === 0) throw new Error('文件校验失败');
    
        // 下载完成后调起系统分享弹窗
        await Sharing.shareAsync(downloadResult.uri, {
          mimeType: 'application/pdf',
          dialogTitle: '保存或分享PDF',
          UTI: 'com.adobe.pdf'
        });
    
        // 没有抛出错误就说明用户完成了保存/分享操作,标记为已完成
        currentStatus = PDF_STATUS.COMPLETED;
    
        // 操作完成后可按需删除临时文件,避免占用存储空间
        await FileSystem.deleteAsync(downloadResult.uri, { idempotent: true });
    
      } catch (error) {
        // 判断错误类型:如果是用户主动关闭分享弹窗、取消下载,标记为已取消
        if (error.message.includes('User did not share') || error.message.includes('cancelled')) {
          currentStatus = PDF_STATUS.CANCELED;
        } else {
          // 其他网络、权限类错误可以单独做失败提示,不属于三类状态范畴可自行处理
          console.error('PDF操作失败:', error);
        }
      }
    
      // 最终把currentStatus返回给UI层,同步展示对应提示即可
      return currentStatus;
    }
    

避坑说明

  • 绝对不要直接传远程URL给Sharing.shareAsync,这是之前拿不到下载完成状态的核心原因,这种模式下整个下载流程对前端是黑盒,没有任何回调可以监听。
  • 安卓10及以上版本不需要额外申请存储权限即可完成文件保存,安卓9及以下版本需要先申请存储权限再调用上述逻辑,否则会保存失败。
  • 如果不需要调起分享弹窗、只需要直接把PDF下载到用户设备存储目录,可以直接用expo-file-system的下载方法把文件存到系统文档目录,不需要调用expo-sharing,下载完成的回调可以直接标记为已完成状态。

内容的提问来源于stack exchange,提问作者Lewis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 11:24:09