目录

文件下载分享功能常见问题

Q:对于文件下载并分享给三方,是应用开发过程中常见的一类场景,那么,如何实现文件下载并打开分享功能呢?

A:实现文件下载并打开分享功能可参考如下流程进行:

各步骤实现样例参考如下:

完整代码如下:

downLoad2Share() {
    // 获取UIContext
    const uiContext = this.getUIContext();
    // 通过UIContext获取PromptAction实例
    const promptAction = uiContext.getPromptAction();
    let context = uiContext.getHostContext() as common.UIAbilityContext;
    this.getTime();
    this.filePath = this.dirPath + '/' + this.fileName;
    try {
      // 判断是否已下载过文件
      let res = fs.accessSync(this.filePath);
      if (res) {
        promptAction.showToast({
          message: '文件已存在'
        });
        let uri = fileUri.getUriFromPath(this.filePath);
        this.shareData(context, uri);
      } else {
        // 此处地址实际使用过程中替换为真实地址
        let url = 'xx://xx.xx.xx/xxxx.pdf';
        // 下载文件
        request.downloadFile(context, {
          // 替换下载地址
          url: url,
          // 文件下载后保存的沙箱路径
          filePath: this.filePath
        }).then((downloadTask: request.DownloadTask,) => {
          let progressCallback = (receivedSize: number, totalSize: number) => {
            this.progress = ((receivedSize / totalSize) * 100).toFixed(2);
            promptAction.showToast({
              message: `下载进度:${this.progress}%`,
              duration: this.showProgress,
            });
          };
          downloadTask.on('progress', progressCallback);
          // 开启回调
          downloadTask.on('complete', () => {
            this.showProgress = 0;
            let uri = fileUri.getUriFromPath(this.filePath);
            promptAction.showToast({
              message: `下载完成,存储目录:${uri}`
            });
            this.shareData(context, uri);
          });
        }).catch((err: BusinessError) => {
          // 下载请求失败回调,可以弹窗提示失败
          if (err.code == 13900015) {
            console.info('目录已存在');
          } else {
            console.info(JSON.stringify(err));
          }
        });
      }
    } catch (error) {
      // 下载请求失败回调,可以弹窗提示失败
      let err: BusinessError = error as BusinessError;
      console.error(`Invoke downloadTask downloadFile failed, code is ${err.code}, message is ${err.message}`);
    }
  }

实现效果:

Q:文件下载到沙箱失败,报错Invoke downloadFile failed,code is 13400003。

A:在使用request.downloadFile()接口时,需要保证存储下载文件的父级路径必须存在。

Q:使用request.downloadFile()下载文件,使用的非文件后缀结尾的url,下载成功后文件无法查看。

A:使用request.downloadFile()下载后的沙箱文件默认文件名从url的最后一个"/"后截取,使用非文件后缀结尾的url则下载后的沙箱文件不是一个正常的文件名,故无法正常查看。可以在下载任务的配置信息DownloadConfig中设置下载路径filePath,示例代码如下:

import { request } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';

@Entry
@Component
struct Page {
  private context = this.getUIContext().getHostContext() as common.UIAbilityContext;

  build() {
    RelativeContainer() {
      Button('点击下载')
        .onClick(() => {
          request.downloadFile(this.context, {
            url: 'https://xxx/test.pdf?parama=a',
            filePath: this.context.cacheDir + '/test.pdf',
            header: {
              'User-Agent': '',
            },
          }).then((data: request.DownloadTask) => {
            console.info('data=', data);
          });
        });
    }
    .height('100%')
    .width('100%');
  }
}

Q:使用request.downloadFile下载文件失败后,fs.accessSync判断文件是否存在仍返回true,如何避免误判?

A:request.downloadFile在开始下载时可能会先创建目标文件(或临时文件),若下载中途失败(如网络中断、服务器错误),该文件可能已存在但内容不完整,fs.accessSync不会抛出异常,导致误判文件存在。建议在下载失败的回调中删除该不完整文件,或在下载完成时校验文件大小来确认文件完整性。

Q:下载文件保存到沙箱后,调起分享另存为到本地目录,文件大小为0,如何解决?

A:拼接文件沙箱路径时,若文件名前多了一个"/"(如dirPath + '/' + '/' + fileName),虽然在沙箱中可以正常读写,但分享时无法正常将文件保存或分享给其他应用,导致文件大小为0。应确保路径中文件名前只有一个"/",正确写法为dirPath + '/' + fileName。