通过 Blob 对二进制流文件下载实现文件保存下载

原理:前端将二进制文件做转换实现下载: 请求后端接口->接收后端返回的二进制流(通过二进制流(Blob)下载,把后端返回的二进制文件放在 Blob 里面)->再通过file-saver插件保存

页面上使用:

bash 复制代码
<span @click="downloadFile">下载当前文件模板</span>

downloadFile() {
	let dowloadUrl
	if (this.dowloadUrl) {
	    dowloadUrl = this.dowloadUrl 
	}else if (this.fullPathUrl) {
	    dowloadUrl = this.fullPathUrl
	}
   downloadGet(dowloadUrl, `${this.fileName}.csv`, {})
},

保存文件:

bash 复制代码
import { saveAs } from 'file-saver'

发起请求通用方法(更改 axios 的 responseType):

bash 复制代码
// 通用下载方法,blob形式--【post请求】
export function download(url, params, filename, config) {
  downloadLoadingInstance = Loading.service({
    text: '正在下载数据,请稍候',
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.7)'
  })
  return service
    .post(url, params, {
      transformRequest: [
        (params) => {
          return tansParams(params)
        }
      ],
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      responseType: 'blob', // 指定响应类型为二进制数据
      ...config
    })
    .then(async(data) => {
      const isLogin = await blobValidate(data)
      if (isLogin) {
        const blob = new Blob([data])
        saveAs(blob, filename)
      } else {
        const resText = await data.text()
        const rspObj = JSON.parse(resText)
        const errMsg =
          errorCode[rspObj.code] || rspObj.msg || errorCode['default']
        Message.error(errMsg)
      }
      downloadLoadingInstance.close()
    })
    .catch((r) => {
      console.error(r)
      Message.error('下载文件出现错误,请联系管理员!')
      downloadLoadingInstance.close()
    })
}
bash 复制代码
// 通用下载方法,blob形式--【get请求】
export function downloadGet(url, filename, config) {
  downloadLoadingInstance = Loading.service({
    text: '正在下载数据,请稍候',
    spinner: 'el-icon-loading',
    background: 'rgba(0, 0, 0, 0.7)'
  })
  return service
    .get(url, {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      responseType: 'blob',// 指定响应类型为二进制数据
      ...config
    })
    .then(async(data) => {
      const isLogin = await blobValidate(data)
      if (isLogin) {
        const blob = new Blob([data])
        saveAs(blob, filename)
      } else {
        const resText = await data.text()
        const rspObj = JSON.parse(resText)
        const errMsg =
          errorCode[rspObj.code] || rspObj.msg || errorCode['default']
        Message.error(errMsg)
      }
      downloadLoadingInstance.close()
    })
    .catch((r) => {
      console.error(r)
      Message.error('下载文件出现错误,请联系管理员!')
      downloadLoadingInstance.close()
    })
}

封装的方法:

bash 复制代码
/**
* 参数处理
* @param {*} params  参数
*/
export function tansParams(params) {
  let result = ''
  for (const propName of Object.keys(params)) {
    const value = params[propName]
    var part = encodeURIComponent(propName) + '='
    // if (value !== null && value !== "" && typeof (value) !== "undefined") {
    if (value !== null && typeof (value) !== 'undefined') {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && value[key] !== '' && typeof (value[key]) !== 'undefined') {
            const params = propName + '[' + key + ']'
            var subPart = encodeURIComponent(params) + '='
            result += subPart + encodeURIComponent(value[key]) + '&'
          }
        }
      } else {
        result += part + encodeURIComponent(value) + '&'
      }
    }
  }
  return result
}

// 验证是否为blob格式
export async function blobValidate(data) {
  try {
    const text = await data.text()
    JSON.parse(text)
    return false
  } catch (error) {
    return true
  }
}


// errorCode.js: 
export default {
  '401': '认证失败,无法访问系统资源',
  '403': '当前操作没有权限',
  '404': '访问资源不存在',
  'default': '系统未知错误,请反馈给管理员'
}

点击"下载":



相关技术

Blob

概念: Blob 对象表示一个不可变的, 原始数据的类文件对象,它的数据可以按文本或二进制格式进行读取。

Blob 构造函数

bash 复制代码
const aBlob = new Blob(array, option)

第一个参数是一个类数组, 必填

第二个参数非必填有两个属性: type, 表示MIME类型, 默认值是''。还有一个是endings 表示 /n 换行符如何被写入,默认值是'transparent'保持不变, 还有'native'按照宿主机的换行符

总结

前端实现文件的下载主要有两种方式,直接打开下载链接和通过 Blob 对二进制流文件下载,实际用那种方法可以看后端的返回值和请求方式

其他:

根据返回值构造 Blob 函数并转换成 URL ,动态创建 a 标签打开 URL参考:
https://huaweicloud.csdn.net/63a55dc4b878a545459452ae.html

相关推荐
anyup_前端梦工厂2 小时前
了解几个 HTML 标签属性,实现优化页面加载性能
前端·html
前端御书房2 小时前
前端PDF转图片技术调研实战指南:从踩坑到高可用方案的深度解析
前端·javascript
2301_789169542 小时前
angular中使用animation.css实现翻转展示卡片正反两面效果
前端·css·angular.js
风口上的猪20153 小时前
thingboard告警信息格式美化
java·服务器·前端
程序员黄同学3 小时前
请谈谈 Vue 中的响应式原理,如何实现?
前端·javascript·vue.js
爱编程的小庄4 小时前
web网络安全:SQL 注入攻击
前端·sql·web安全
宁波阿成5 小时前
vue3里组件的v-model:value与v-model的区别
前端·javascript·vue.js
柯腾啊5 小时前
VSCode 中使用 Snippets 设置常用代码块
开发语言·前端·javascript·ide·vscode·编辑器·代码片段
weixin_535854225 小时前
oppo,汤臣倍健,康冠科技,高途教育25届春招内推
c语言·前端·嵌入式硬件·硬件工程·求职招聘
扣丁梦想家5 小时前
设计模式教程:装饰器模式(Decorator Pattern)
java·前端·装饰器模式