Skip to content

Instantly share code, notes, and snippets.

@zxhfighter
Last active October 29, 2019 07:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zxhfighter/8114f85a684bcaca0181aa2f515115a6 to your computer and use it in GitHub Desktop.
Save zxhfighter/8114f85a684bcaca0181aa2f515115a6 to your computer and use it in GitHub Desktop.
blob 各种应用场景

Blob

应用背景是,不想暴露下载地址(例如一些视频网站防止视频抓取),这时候就在后端根据文件地址直接转成二进制流形式,返回给前端合并,再进行下载。

可以使用 Blob 处理二进制流,进行文件下载。

语法

{
    type: string; // MIME 类型
    endings: 'transparent' | 'native'; // 决定第一个参数的数据格式
}

下载

一个下载文本的例子如下。

// 下载文本
function downloadText(str) {
    const blob = new Blob([str], { type: 'text/plain;charset=utf-8' });
    const blobUrl = URL.createObjectURL(blob); // blob:http://xxx
    const link = document.createElement('a');
    link.href = blobUrl;
    link.download = 'address.txt';
    document.body.appendChild(link);
    link.click();
    link.remove();
}

downloadText(['abc', 'def'].join('\n'));

一个下载PDF的例子如下。

// content 为字节流
let content = await downloadContract(params);

// 前端没有 Buffer 对象吧
const buf = Buffer.from(content, 'binary');
let blob = new Blob([buf], {type: 'application/pdf'});

const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'address.pdf';
document.body.appendChild(link);
link.click();
link.remove();

一个下载 Excel 的例子如下。

var blob = new Blob([res.data], {type: 'applicationnd.ms-excel'});
var downloadUrl = URL.createObjectURL(blob);
console.log(downloadUrl);
var a = document.createElement("a");
a.href = downloadUrl;
a.download = "data.xlsx";
document.body.appendChild(a);
a.click();

分片上传

File继承自Blob,因此我们可以调用slice方法对大文件进行分片上传。

function uploadFile(file) {
  var chunkSize = 1024 * 1024;   // 每片1M大小
  var totalSize = file.size;
  var chunkQuantity = Math.ceil(totalSize/chunkSize);  //分片总数
  var offset = 0;  // 偏移量

  var reader = new FileReader();
  reader.onload = function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST","http://xxxx/upload?fileName="+file.name);
    xhr.overrideMimeType("application/octet-stream");

    xhr.onreadystatechange = function() {
      if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
        ++offset;
        if(offset === chunkQuantity) {
          alert("上传完成");
        } else if(offset === chunkQuantity-1){
          blob = file.slice(offset*chunkSize, totalSize);   // 上传最后一片
          reader.readAsBinaryString(blob);
        } else {
          blob = file.slice(offset*chunkSize, (offset+1)*chunkSize);
          reader.readAsBinaryString(blob);
        }
      }else {
        alert("上传出错");
      }
    }

    if(xhr.sendAsBinary) {
      xhr.sendAsBinary(e.target.result);   // e.target.result是此次读取的分片二进制数据
    } else {
      xhr.send(e.target.result);
    }
  }
   var blob = file.slice(0, chunkSize);
   reader.readAsBinaryString(blob);
}

创建图片资源地址

为上传图片文件创建一个Blob URL,赋值给<img>标签:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Blob Test</title>
    <script>
        function handleFile(e) {
            var file = e.files[0];
            var blob = URL.createObjectURL(file);
            var img = document.getElementsByTagName("img")[0];
            img.src = blob;
            img.onload = function(e) {
                URL.revokeObjectURL(this.src);  // 释放createObjectURL创建的对象##
            }
        }
    </script>
</head>

<body>
    <input type="file" accept="image/*" onchange="handleFile(this)" />
    <br/>
    <img style="width:200px;height:200px">
</body>

</html>

参考

https://www.jianshu.com/p/4d014a45aaf7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment