• 网页中直接下载 PDF 文件而不打开新的页面加载 PDF 文件


    我们知道 <a> 元素有 download 属性,表示当前链接不是用来浏览的,而是用来下载的。它的值是一个字符串,表示用户下载得到的文件名。可是对于 PDF 文件,浏览器默认打开一个新的页面加载 PDF 文件,而不会直接下载该文件。

    这时候我们需要将原来的用于下载的 url 进行转换,转换成一个 Blob 对象的 URL

    一、用 Blob 对象来读写 PDF 文件

    引入 Blob 对象,用 BlobBinary Large Object 二进制大型文件) 对象来读写 PDF 文件。

    浏览器原生提供 Blob() 构造函数,用来生成实例对象。

    new Blob(array [, options])
    

    Blob 构造函数接受两个参数。第一个参数是数组,成员是字符串或二进制对象,表示新生成的 Blob 实例对象的内容;第二个参数是可选的,是一个配置对象,目前只有一个属性 type,它的值是一个字符串,表示数据的 MIME 类型,默认是空字符串。

    let htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
    let myBlob = new Blob(htmlFragment, { type: 'text/html' });
    

    上面代码中,实例对象 myBlob 包含的是字符串。生成实例的时候,数据类型指定为 text/html

    下面是另一个例子,Blob 保存 JSON 数据。

    let obj = { hello: 'world' };
    let blob = new Blob([JSON.stringify(obj)], { type: 'application/json' });
    
    blob; // Blob {size: 17, type: "application/json"}
    

    对于 MIME 类型,需要选择适合二进制文件流的类型,而不是普通的文本类型:(MIME 类型)

    浏览器通常使用 MIME 类型(而不是文件扩展名)来确定如何处理 URL,因此 Web 服务器在响应头中添加正确的 MIME 类型非常重要。如果配置不正确,浏览器可能会曲解文件内容,网站将无法正常工作,并且下载的文件也会被错误处理。

    还有一种很重要的 MIME 类型 application/octet-stream

    这是应用程序文件的默认值。意思是 未知的应用程序文件 ,浏览器一般不会自动执行或询问执行。浏览器会像对待 设置了 HTTPContent-Disposition 值为 attachment 的文件一样来对待这类文件。

    二、通过 URL.createObjectURL() 方法将 Blob 对象转换成 url

    URL.createObjectURL() 方法将流媒体文件生成一个 URL 字符串。这个字符串代表了 Blob 对象的 URL

    该方法生成的 URL 就像下面的样子(以 blob: 开头的字符串)。

    blob:http://localhost:3209/28c3a781-3492-4cff-82cc-2f72a0a7f245
    

    至此我们就拿到了 Blob 对象的 URL


    当我们拿到下载 PDF 文件的地址(url)和 PDF 文件名(name)后,先转换成二进制文件流的 url,然后就可以下载该文件了。

    handlePdfLink(url: string, name: string): void {
      fetch(url, {
        method: 'get'
      })
        .then(function (res) {
          if (res.status !== 200) {
            return res.json()
          }
          return res.arrayBuffer()
        })
        .then((blobRes) => {
          // 生成 Blob 对象,设置 type 等信息
          const e = new Blob([blobRes], {
            type: 'application/octet-stream'
          })
          // 将 Blob 对象转为 url
          this.blobLink = window.URL.createObjectURL(e)
    
          this.downloadFile(this.blobLink, name)
        }).catch(err => {
          console.error(err)
        })
    }
    

    上面代码中 arrayBuffer() 将产生一段二进制数据。Response.arrayBuffer()

    arrayBuffer() 接受一个 Response 流, 并等待其读取完成. 它返回一个 promise 实例, 并 resolve 一个 ArrayBuffer 对象。

    然后将文件的MIME 类型设置为 application/octet-stream 让浏览器不会自动执行或询问执行,装入 Blob 对象中进行读取文件的数据内容。

    再使用 URL.createObjectURL() 方法,针对 Blob 对象生成一个临时 URL,以便于某些 API 使用。这个 URLblob: 开头,表明对应一个 Blob 对象,协议头后面是一个识别符,用来唯一对应内存里面的 Blob 对象。这一点与 data://URLURL 包含实际数据)和 file://URL(本地文件系统里面的文件)都不一样。

    最后我们添加 <a> 元素给它装入下载地址 url 和下载文件名 name 来下载 PDF 文件。

    downloadFile(url: string, name: string): void {
      if (url && url.trim()) {
        let a = document.createElement('a');
        a.href = url;
        a.download = name || '未命名文件';
        a.click();
        window.URL.revokeObjectURL(this.blobLink);
      } else {
        this.msg.remove();
        this.msg.error('文件下载路径不能为空!');
      }
    }
    

    由于每次使用 URL.createObjectURL() 方法,都会在内存里面生成一个 URL 实例。如果不再需要该方法生成的 URL 字符串,为了节省内存,下载完成后可以使用 URL.revokeObjectURL() 方法释放这个实例。

    欢迎写出你的看法,一起成长!
  • 相关阅读:
    防抖和节流
    关于keep-alive的学习
    elementUI上传图片前判断图片的尺寸大小
    vue 判断线上环境还是本地环境
    elementUi table表格的拖拽功能
    获取文件的md5值
    element ui上传腾讯云,更新视频时长
    js音视频文件的时长
    手写一个移动端带惯性的轮播图vue组件
    这个用来总结一些常用的工具函数
  • 原文地址:https://www.cnblogs.com/xinjie-just/p/15035726.html
Copyright © 2020-2023  润新知