当前位置: 首页 > 知识库问答 >
问题:

vue.js - Vue H5+ App 如何实现文件流下载到手机?

杭志泽
2025-10-31

使用vue开发的app,用的是hbuilderx创建h5+app项目来打包的,现在有一个附件下载功能,后端返回的文件流,前端怎样将文件下载到手机中

试过plus.io里面的方法,但没成功,希望有大佬提供处理方法

共有2个答案

阴礼骞
2025-10-31

忘记之前从哪里借鉴的了,反正就是用了 5plus 的能力来下载。主要用到了 plus.downloader.createDownload 和 plus.io.convertLocalFileSystemURL 两个API。

因为上的比较急,没有考虑健壮性,单纯跑通了就这样用了。

import { ElMessage } from 'element-plus'

/**
 * 监听 5plus 的 ready 事件
 * @returns {Ref<boolean>} 5plus 是否 ready
 */
export const use5PlusReady = () => {
  const ready5Plus = ref(!!window?.plus)
  document.addEventListener("plusready", () => {
    ready5Plus.value = true
  }, false);
  return ready5Plus
}

/**
 * 使用 5Plus 能力下载文件
 * @param url 文件地址,需要是完整的文件地址
 * @param options 下载选项
 * @returns {Promise<string>} 文件地址
 */
export const downloadFileBy5Plus = (url: string, options?: PlusDownloaderDownloadOptions): Promise<string> => {
  return new Promise((resolve, reject) => {
    const dTask = plus.downloader.createDownload(url, options, (dFile, dStatus) => {
      if (dStatus === 200) {
        resolve(plus.io.convertLocalFileSystemURL(dFile.filename))
      } else {
        const errorMsg = dStatus === 404 ? 'File not found' : `Download file failed: ${dStatus}`
        ElMessage.error(errorMsg)
        reject({
          msg: errorMsg,
          status: dStatus,
          file: dFile,
          filePath: url
        })
      }
    })
    dTask.start()
  })
}

/**
 * 调用第三方程序打开指定的文件
 * @param fileUrl 文件地址
 * @param options 打开选项
 * @param errorCB 错误回调
 */
export const openFileBy3rdApp = (fileUrl: string, options?: PlusRuntimeOpenFileOptions, errorCB?: (error: string) => void) => {
  plus.runtime.openFile(fileUrl, options, errorCB)
}

/**
 * 调用第三方程序打开指定的URL
 * @param url 文件地址
 * @param errorCB 错误回调
 */
export const openWebUrlBy3rdApp = (url: string, errorCB?: (error: string) => void) => {
  plus.runtime.openURL(url, errorCB)
}

用的时候就是这样:

// 下载文件
const handleClickFileDownload = (item: FileItem) => {
  const ready5Plus = use5PlusReady()
  const fileUrl = `/file-sys/${item.bucketName}/${item.fileName}`
  if (ready5Plus.value) {
    const fileFullPath = (import.meta.env.VITE_BASE_URL + fileUrl).replace(/\/\//, '/')
    downloadFileBy5Plus(fileFullPath).then(openFileBy3rdApp)
  } else {
    downBlobFile(fileUrl, null, item.original)
  }
}
夹谷浩宕
2025-10-31

在 Vue H5+ App 中实现文件流下载到手机,可通过以下步骤操作(使用 plus.ioplus.downloader API):

解决方案代码

import axios from 'axios';

// 文件下载方法
const downloadFile = async (fileUrl, fileName) => {
  try {
    // 1. 获取文件流 (responseType 必须是 'arraybuffer' 或 'blob')
    const response = await axios.get(fileUrl, {
      responseType: 'arraybuffer', // 关键:接收二进制数据
      headers: { /* 如有 token 等需添加 */ }
    });

    // 2. 将 ArrayBuffer 转为 Base64
    const base64Data = arrayBufferToBase64(response.data);
    
    // 3. 保存到手机本地
    plus.io.resolveLocalFileSystemURL('_doc/', (entry) => {
      entry.getFile(fileName, { create: true }, (fileEntry) => {
        fileEntry.createWriter((writer) => {
          writer.onwrite = () => {
            plus.nativeUI.toast(`下载成功:${fileName}`);
            console.log('文件路径:', fileEntry.toLocalURL());
          };
          writer.onerror = (e) => console.error('写入失败:', e.message);
          
          // 写入 Base64 数据
          writer.writeAsText(base64Data, 'base64');
        });
      });
    }, (e) => console.error('获取目录失败:', e.message));
    
  } catch (e) {
    console.error('下载失败:', e.message);
    plus.nativeUI.alert('下载失败,请重试');
  }
};

// ArrayBuffer 转 Base64 工具函数
const arrayBufferToBase64 = (buffer) => {
  const binary = [];
  const bytes = new Uint8Array(buffer);
  for (let i = 0; i < bytes.byteLength; i++) {
    binary.push(String.fromCharCode(bytes[i]));
  }
  return window.btoa(binary.join(''));
};

// 调用示例(在 Vue 方法中触发)
this.downloadFile('https://api.example.com/file', 'report.pdf');

关键说明

  1. 数据流转 Base64
    后端返回的文件流需要转为 Base64 格式,因 plus.iowriteAsText 方法支持直接写入 Base64 数据。
  2. 存储目录选择

    • _doc/: 应用私有目录(推荐,无需权限)
    • _downloads/: 系统下载目录(部分安卓需权限)
    • 使用 fileEntry.toLocalURL() 获取完整路径(如:file:///_doc/report.pdf
  3. 权限配置
    manifest.json 中添加以下权限:

    "permissions": {
      "Download": {}
    }
  4. 大文件处理建议
    若文件超过 10MB:

    • 让后端提供直接下载 URL
    • 改用 plus.downloader(简单高效,支持断点续传):

      const task = plus.downloader.createDownload(
      fileUrl, 
      { filename: '_doc/' + fileName },
      (d, status) => status === 200 ? console.log('成功') : console.log('失败')
      );
      task.start();

常见问题排查

  1. 写入失败

    • 检查存储路径是否合法(避免中文/特殊字符)
    • 真机调试查看完整错误日志(HBuilderX -> 控制台)
  2. 跨域问题
    确保后端配置 CORS 响应头:

    Access-Control-Allow-Origin: *
    Access-Control-Expose-Headers: Content-Disposition
  3. 权限拒绝

    • iOS 需在 manifest.jsonios 节点添加:

      "UIFileSharingEnabled": true,
      "accesses": [ "Documents" ]
    • Android 9+ 需适配 FileSystem API
提示:优先考虑让后端提供直链文件 URL,使用 plus.downloader 是最稳定高效的方式,无需处理文件流转换。
 类似资料:
  • 我是GWT和一般Web应用程序的新手。 我正在制作一个GWT web应用程序。它提供的一个功能是通过单击网页上的按钮下载文件。不幸的是,文件本身并不是物理上位于服务器端。服务器端需要通过对另一个web服务的REST调用来获取文件的InputStream。 我的问题是: 如何将流传递到客户端,以便浏览器可以开始下载? 在开始之前,我必须在服务器上物理写入文件吗? 非常感谢 编辑:我找到了这个例子:使

  • 本文向大家介绍JavaEE实现文件下载,包括了JavaEE实现文件下载的使用技巧和注意事项,需要的朋友参考一下  我们先来看一个最简单的文件下载的例子:  该段代码的功能是从服务器端下载图片1.png。目录结构用MyEclipse的package explorer显示如下:   让我们增加一点难度,我们要下载的文件是一个中文名字的文件。由于在http协议中头文件中的东西只能是ASCII字符,因而通

  • 在Vue项目实现文件下载的时候遇到一个问题,无论是使用a标签还是使用windown.open(url)都只会在网页打开预览,但是都不能下载,请问这是什么问题?应该如何去避免从而实现下载功能呢?查了好久资料,来来去去都是那一片文章抄来抄去,实在让人难受!!!这些粘贴怪真恶心!!!

  • 本文向大家介绍如何利用python web框架做文件流下载的实现示例,包括了如何利用python web框架做文件流下载的实现示例的使用技巧和注意事项,需要的朋友参考一下 hello 大家好, 前不久公司里有个需求,把时序数据库中的日志下载到本地. 大家都知道. 数据库里的数据 都是存在数据库里的(废话). 想把他下载到客户的本地. 有的同学第一反应是: 只有文件才能下载. 所以大多数同学会想到先

  • 本文向大家介绍PHP实现远程下载文件到本地,包括了PHP实现远程下载文件到本地的使用技巧和注意事项,需要的朋友参考一下 代码很简单就不多废话了,直接奉上: 再来个远程下载文件到服务器 以上所述就是本文的全部内容了,希望大家能够喜欢。

  • 本文向大家介绍Spring Mvc下实现以文件流方式下载文件的方法示例,包括了Spring Mvc下实现以文件流方式下载文件的方法示例的使用技巧和注意事项,需要的朋友参考一下 项目中需要对一个点击事件进行下载操作,同时通过点击事件,已经可以从jsp页面获取到需要访问的URL和下载的文件名(数据库获取,jsp页面显示)。点击事件JS如下: 该ajax调用后台(checkDownload)方法,首先判

  • 本文向大家介绍SpringMVC实现文件下载功能,包括了SpringMVC实现文件下载功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了SpringMVC文件下载的具体代码,供大家参考,具体内容如下 两个案例   1.为登录用户提供下载服务。   2.阻止仅通过输入网址即可获取下载。 文件下载概览   为了将文件发送给浏览器,我们需要在控制器中完成以下操作: 对请求处理方法使用vo

  • 本文向大家介绍vue+axios实现post文件下载,包括了vue+axios实现post文件下载的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了vue+axios实现post文件下载的具体代码,供大家参考,具体内容如下 功能:点击导出按钮,提交请求,下载excel文件; 这里是axios的post方法。get方法请点击这里=》here  第一步:跟后端童鞋确认交付的接口的respo