前端实现预览流式 PDF 数据

161 阅读1分钟

为什么不能直接使用 <embed> 标签预览流式 PDF 数据?

  1. <embed> 标签的src属性
    • <embed> 标签的 src 属性通常需要一个有效的 URL,指向一个外部资源(如文件路径、网络地址等)
    • 流式数据(如 ReadableStreamBlob)不能直接作为 src 属性的值
  2. 浏览器的处理方式
    • 浏览器在处理 <embed> 标签时,会根据 src 属性指定的 URL 发起网络请求,获取外部资源并嵌入到页面中
    • 流式数据无法直接作为 URL 使用,因此浏览器无法正确处理

预览 pdf 的流式数据的解决办法

把可读流转成 Blob,再将 Blob 转成一个可临时访问的 url,代码示例如下:

<script>
  export default {
    methods: {
      /**
     * 将流转换为 Blob
     * @param stream
     * @returns Blob
     */
      async streamToBlob(stream) {
        const reader = stream.getReader()
        const chunks = []

        let done = false
        while (!done) {
          const { done: isDone, value } = await reader.read()
          done = isDone
          if (!done) {
            chunks.push(value)
          } else {
            // 流读取完成的逻辑
          }
        }

        return new Blob(chunks, { type: 'application/pdf' })
      },
      /**
     * 预览 PDF
     * @param url
     */
      async previewPDF(url) {
        try {
          const response = await fetch(url)
          if (!response.ok) {
            throw new Error('加载 pdf 失败')
          }

          const blob = await this.streamToBlob(response.body)
          const blobUrl = URL.createObjectURL(blob)
          this.blobUrl[this.currentIndex] = blobUrl
        } catch (e) {
          this.$modal.msgError('加载 pdf 失败')
        }
      },
    }
  }
</script>