zoukankan      html  css  js  c++  java
  • 利用 Blob 处理 node 层返回的二进制文件流字符串并下载文件

    博客地址: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.readFilebinary 编码读取得到,但没必要下载,下载完还要删除,多此一举

    前端处理下载

    问题来了,也是坑了我一个下午的问题,如何在前端 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://ainyi.com/65

  • 相关阅读:
    oracle 数据库服务名怎么查
    vmware vsphere 6.5
    vSphere虚拟化之ESXi的安装及部署
    ArcMap中无法添加ArcGIS Online底图的诊断方法
    ArcGIS中字段计算器(高级计算VBScript、Python)
    Bad habits : Putting NOLOCK everywhere
    Understanding the Impact of NOLOCK and WITH NOLOCK Table Hints in SQL Server
    with(nolock) or (nolock)
    What is “with (nolock)” in SQL Server?
    Changing SQL Server Collation After Installation
  • 原文地址:https://www.cnblogs.com/ainyi/p/10242117.html
Copyright © 2011-2022 走看看