vue 接收后端文件流 或 非文件流下载方法

目录 

  后端返回二进制文件流下载

  非文件流下载方法(后端直接给你文件在服务器中的地址)


 后端返回二进制文件流下载

首先文件流在浏览器展示乱码, 所以我们需要在请求中添加responseType: "blob", 告诉浏览器回调类型让其解析blob,以便我们创建Blob实例并解析

通常情况下在上传文件时我们的file中会告诉后端文件类型(每种文件类型对应一种MIME类型), 所以我们下载时可以直接让后端返回文件流的类型

// 下载文件的函数
async function handleDownload() {
  // 调用下载文件的API,返回文件二进制内容
  const res = await requestDownloadFile({ path: path.value })
  downloadFile(res)
}

// 文件流解析并下载
function downloadFile(res) {
  const blob = new Blob([res], { type: res.type })
  // 创建一个a标签,将Blob对象作为URL,设置下载属性和文件名
  const link = document.createElement('a')
  link.href = window.URL.createObjectURL(blob)
  link.download = new Date().getTime()
  // 添加a标签到body中,模拟点击下载链接,完成下载后移除a标签
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

 由于种种原因后端没权限修改主系统上传下载代码(后端上传时加个字段接下的事)( -_- ), 因此出此下策:通过对应文件类型匹配MIME类型,通过Blob告诉浏览器我们下载文件的类型

// 定义一个MIME类型字典
const dict = {
  png: 'image/png',
  jpg: 'image/jpeg',
  jpeg: ' image/jpeg',
  bmp: 'image/bmp',
  doc: 'application/msword',
  docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  xls: 'application/vnd.ms-excel',
  pdf: 'application/pdf',
  zip: 'application/zip',
  rar: 'application/x-rar-compressed',
}

/**
 * 正则截取文件后缀名
 * @param {String} fileName 文件名称
 * @returns 文件类型
 * @example fileExtReg('logo.png')
 */
function fileExtReg(fileName) {
  return fileName.match(/\.([^.]+)$/)[1];
}

// 下载文件的函数
async function handleDownload() {
  // 调用下载文件的API,返回文件二进制内容
  const res = await requestDownloadFile({ path: path.value })
  downloadFile(res)
}

// 文件流解析并下载
function downloadFile(res) {
  // 将文件内容转成Blob对象,并设置MIME类型
  const blob = new Blob([res], { type: dict[fileExtReg(name.value)] })
  // 创建一个a标签,将Blob对象作为URL,设置下载属性和文件名
  const link = document.createElement('a')
  link.href = window.URL.createObjectURL(blob)
  link.download = new Date().getTime()
  // 添加a标签到body中,模拟点击下载链接,完成下载后移除a标签
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}
非文件流下载方法(后端直接给你文件在服务器中的地址)
/**
 * *下载:需要注意的是,如果要确保文件下载时的兼容性和安全性,还需要在服务器端设置相关的响应头信息,例如设置 Content-Disposition 为 attachment。
 * @param {String} url 地址
 */
function handleDownload(url) {
  window.open(xxxxxxx, "_blank");
}
/**
 * *下载:通过创建一个a标签,并将其链接地址指向要下载的文件,然后模拟用户点击该标签来触发文件下载操作。这种下载方式还可以通过download修改下载文件名称等
 * @param {String} url 地址
 */
function downloadFile(url) {
  var link = document.createElement("a");
  link.href = url;
  link.target = "_blank"; 
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}
文件流:文件名问题

一般来说,文件名字后端都在返回响应头里response.headers["content-disposition"],前后端可以约定文件名前用 ‘某’ 符号分隔。以便前端截取并进行解码处理,文件名称默认是URL编码后的字符串,如不是需要问一下后端格式,再作相应的解码
decodeURIComponent()该内置对象,接收编码后的部分,从而返回解码后的内容

// 假设str是response.headers['content-disposition']返回的文件名
let str = "filename=%E6%B5%8B%E8%AF%95.zip"
const fileTxt = response.headers['content-disposition'].split('=')[1].replace(/^"|"$/g, '')
console.log(fileTxt) // e6b58be8af95.txt
const fileName = fileTxt.split('.')[0] // 文件名
const fileType = fileTxt.split('.')[1] // 文件类型
const decodeFileName = decodeURIComponent(fileName)
// 此时已经解决文件名/文件类型的问题,将响应体返回
return {
  data: {
    fileType,
    fileName: decodeFileName,
  },
  fileStream: response.data, // 文件流
}

// 后续没什么好说的,上方讲过: 文件流解析并下载
// 定义一个MIME类型字典
const dict = {
  png: 'image/png',
  jpg: 'image/jpeg',
  jpeg: ' image/jpeg',
  bmp: 'image/bmp',
  doc: 'application/msword',
  docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  xls: 'application/vnd.ms-excel',
  pdf: 'application/pdf',
  zip: 'application/zip',
  rar: 'application/x-rar-compressed',
}
function downloadFile(res) {
  // 将文件内容转成Blob对象,并设置MIME类型
  const blob = new Blob([res.fileStream], { type: dict[res.data.fileType] })
  // 创建一个a标签,将Blob对象作为URL,设置下载属性和文件名
  const link = document.createElement('a')
  link.href = window.URL.createObjectURL(blob)
  link.download = new Date().getTime()
  // 添加a标签到body中,模拟点击下载链接,完成下载后移除a标签
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Write λ Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值