为了账号安全,请及时绑定邮箱和手机立即绑定

利用 Blob 处理 node 层返回的二进制文件流字符串并下载文件

标签:
Node.js

博客地址https://ainyi.com/#/65

解释 | 背景

看到标题有点懵逼哈哈实际上是后端将文件处理成二进制流返回到前端前端处理这个二进制字符串输出文件或下载

最近公司有个需求是用户在点击下载文件==pdf==的时候下载地址不能暴露在接口的返回值前端不要通过这个地址下载容易发生泄露不安全。所以经过讨论就在后端根据文件地址直接转成二进制流形式返回给前端合并再进行下载

文件转换二进制流

在 nodejs 中将文件转换成二进制是比较简单的先通过接口获取文件下载地址由于是不同域的地址也就是必须通过网络请求得到这个文件不能使用 ==fs.readFile== 读取文件可以使用 ==get== 请求获取读写编码设置成二进制 ==binary==

// 后端 node 所写的接口(部分代码)download() {  let { ctx } = this
  // 根据传入的参数 contractNumber查询得到文件地址 data.formalPdfUrl / data.draftPdfUrl
  // 查询...
  let url = data.formalPdfUrl || data.draftPdfUrl // 简便写法
  // 上面是简便写法相当于
  // if (data.formalPdfUrl) {
  //   url = data.formalPdfUrl
  // } else if (data.draftPdfUrl) {
  //   url = data.draftPdfUrl
  // }
  let handle = this.handleFiles(url)  let binaryFiles = await handle.then(data => {    return data
  })  // 返回到前端
  ctx.body = binaryFiles
},
handleFiles(url) {  return new Promise((resolve, reject) => {
    http.get(url, res => {
      res.setEncoding('binary') // 二进制
      let files = ''
      res.on('data', chunk => { // 加载到内存
        files += chunk
      }).on('end', () => { // 加载完
        resolve(binaryFiles)
      })
    })
  })
}

提示

当然也可以在后端直接下载这个文件然后使用 ==fs.readFile== 以 ==binary== 编码读取得到但没必要下载下载完还要删除多此一举

前端处理下载

问题来了也是坑了我一个下午的问题如何在前端 js 中处理这个二进制流合并成文件供下载

找了找发现 html5 有个 Blob 对象此对象在数据库中也见过保存庞大数据的字段那么在 html5 中Blob 允许我们可以通过 js 直接操作二进制数据

JavaScript - Blob 对象

一个 Blob 对象表示一个不可变的原始数据的类似文件对象
Blob 表示的数据不一定是一个 JavaScript 原生格式本质上是 js 中的一个对象里面可以储存大量的二进制编码格式的数据

创建 blob 对象本质上和创建一个其他对象的方式是一样的都是使用 Blob() 的构造函数来进行创建

构造函数接受两个参数
第一个参数为一个数据序列可以是任意格式的值
第二个参数是一个包含两个属性的对象

{ type: MIME 类型,
  endings: 决定第一个参数的数据格式可以取值为 "transparent" 或者 "native"
 transparent不变是默认值native按操作系统转换
}

关于 MIME 类型的可看http://www.w3school.com.cn/media/media_mimeref.asp

关于 Blob 对象在这篇博客不讲太多说明主要讲解如何使用 Blob 对象解决二进制流转文件的问题

代码如下

// 前端调用download() {  let params = {    contractNumber: num
  }  // 调用下载文件接口实质转成二进制流
  let content = await downloadContract(params)  // 拿到二进制字符串 content
  // 再利用 Buffer 转为对象
  const buf = Buffer.from(content, 'binary')  // 再输入到 Blob 生成文件
  let blob = new Blob([buf], {type: 'application/pdf'});  let a = document.createElement('a')  // 指定生成的文件名
  a.download = num + '.pdf'
  a.href = URL.createObjectURL(blob)  document.body.appendChild(a)
  a.click()  document.body.removeChild(a)
}

得到 Blob 对象创建的文件 url格式类似“blob:http://.....”赋值到动态创建的 a 标签的 href 属性设置好 download 属性点击下载后移除 a 标签

注意

要注意的是
在 node 层不必使用 Buffer 处理输出二进制对象因为返回给前端的时候还是二进制字符串形式所以 node 层可直接返回二进制流字符串
在前端在调用 Blob 构造函数的时候先利用 Buffer 将二进制字符串转为 Buffer 对象再作为 Blob 的第一个参数指定好第二个参数的类型 type 即可

原文出处;https://www.cnblogs.com/ainyi/p/10242117.html

作者筱月

 


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消