数据处理03 - 后端传二进制pdf内容,前端网页预览实现

902 阅读2分钟

最近有个需求,后端把pdf文件直接传给后端,前端不用下载然后做网页端预览。

pdf预览的话如果知道文件的绝对路径,可以就用一个<a>标签,href属性设为此路径,(<embed>/<iframe>/<object>等标签在有文件路径的情况下都可以直接浏览器预览)点击即可浏览器预览。但是问题是,这个获取pdf文件的接口需要做token校验,而且也不是直接返回一个文件路径给到前端,返回的是二进制数据,需要前端自己处理。

后端返回内容如下:

image.png

直接搜"二进制pdf文件在线预览"会查到很多相关的资料,看了下用的最多的那种方法:用法如下:

      axios({
        url: '/wx/informationentry/download',
        methods: 'get',
        baseURL: BASE_URL,
        headers: {
          Accept: 'application/pdf',
          token: getToken(),
          responseType: 'blob'
        },
        params: {
          id: row.id
        }
      }).then((res) => {
        console.log('文件下载成功:', res)
        const blob = new Blob([res.data], {
          type: 'application/pdf;charset=utf-8'
        })
        // 生成一个本地预览的url
        const url = window.URL.createObjectURL(blob)
        // 创建一个a标签,设置它的href/target属性,并自动点击
        const a = document.createElement('a')
        a.href = url
        a.target = '_blank'
        a.click()
      })

不知道是什么原因,这种方法,可以实现预览,但是预览的都是空白内容,搜了下发现,有的说是axios发送的请求的问题,所以这里改成了原始的XMLHttpRequest方法发送请求。最终我成功实现预览的代码如下:

    downloadFileR(row, fileType) {
      const xhr = new XMLHttpRequest()
      const url = fileType
        ? `${BASE_URL}/wx/informationentry/download?id=${row.id}&fileType=1`
        : `${BASE_URL}/wx/informationentry/download?id=${row.id}`
      xhr.open('get', url, true)
      xhr.responseType = 'blob' // 这个设置必须要
      xhr.setRequestHeader('token', getToken())
      xhr.onload = function () {
        // 生成url
        const binaryData = []
        binaryData.push(this.response)
        const blob = new Blob(binaryData, {
          type: 'application/pdf;charset=utf-8'
        })
        const url = window.URL.createObjectURL(blob)
        // const url = window.URL.createObjectURL(this.response) // 直接这样使用url也可以
        const a = document.createElement('a')
        a.target = '_blank'
        a.href = url
        a.click()
      }
      xhr.send()
    }

注意:

  • 发送请求时xhr.responseType = 'blob'这个设置预览时也是空白的。

  • 生成url部分,可以用红框中的代码,也可以直接用绿框中注释掉的代码不用红框的代码。我这里是两种方法在chrome浏览器上都生效的

image.png