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