图片下载

617 阅读2分钟

一、后端返回二进制流图片问题。

背景

前段时间研究二进制流图片展示遇到了Blob对象,在这里做一下笔记。

content-type: application/octet-stream 二进制数据。

Blob

Binary Large Object的缩写,代表二进制类型的大对象。Blob的存在,允许我们可以通过JS直接操作二进制数据。

blob方法直接操作二进制数据。

通过url下载文件

Blob URL是blob协议得URL,它的格式如下:

blob:http://xxx

Blob URL可以通过URL.createObjectURL(blob)创建。常见得场景有: 作为文件得下载地址和作为图片资源地址。

  • 会产生一个类似 blob:d3958f5c-0777-0845-9dcf-2cb28783acaf 这样的URL字符串
  • 你可以像使用普通 URL 那样使用它,比如用在 img.src 上。

在每次调用createObjectURL()方法时,都会创建一个新的URL对象.

   //axios需要添加responseType:'blob'
    var data = "<div style='color:red;'This is a blob</div>";
    var blob = new Blob([data], {type: 'text/html'}); // 创建Blob对象
    console.log(blob); // Blob {size: 43, type: "text/html"}
    var blobUrl = URL.createObjectURL(blob);
    console.log(blobUrl); // blob:http://localhost:63342/bd736211-1897-402c-a8da-e4f5037fef7f

优化:

URL.revokeObjectURL()方法会释放一个通过URL.createObjectURL()创建的对象URL。资源加载完后,不需要再次加载时,可以通过这个方法进行释放。

www.cnblogs.com/hjbky/p/115…


二、二进制流图片的下载

问题一:如果后端返回二进制流格式的图片,前端如何去下载呢。

  • a标签的href就可以解决,因为浏览器不认识二进制流,使得图片就下载了。

问题二:但是下载的文件名字是url的名字,如何解决这个问题。

  • 可以使用download属性,但是download属性在跨域时是无效的。
  • 解决方案时:ajax请求服务,下载到本地,这样download属性就起作用了。
utils.forceDownload = (url, filename) => {
    if (!filename) {
        filename = url.split('\').pop().split('/').pop().replace(/?.*$/, '');
    }
    fetch(url, {
        headers: new Headers({
            'Origin': location.origin
        }),
        mode: 'cors'  // 跨域访问
    }).then(response => response.blob())  // 将资源下载的到本地了。response 是乱码的流,blob()解决乱码流的问题。
      .then(blob => {
          const blobUrl = window.URL.createObjectURL(blob);
          const a = document.createElement('a');
          a.download = filename;
          a.href = blobUrl;
          a.click();
    }).catch(e => {
        console.log(e)
    });
};

三、普通图片的下载

问题一:后端返回的content-type: img/jpg这种图片格式的。

a的href 预览功能,因为浏览器认识它。

想要下载,就强制下载,加download属性,回到上面的问题2。下载到本地加download。

四、代码简化问题带来的思考

    if (temp) {
        if(temp.totalAmountLimit) {
          this.sumPayAmount = temp.totalAmountLimit;
        }else {
          this.sumPayAmount = '';
        }
      }
     // 上面的代码用下面替换。
      this.sumPayAmount = temp && temp.totalAmountLimit || '';

思考: && 与 || 运算符

总的是:短路计算 ,要么返回a,要么返回b,打破了我之前 ture和false的认知。
优先级,&&优先级别大于 || 。

image.png

image.png