一、下载逻辑
【先区分是请求方式】
1、get请求
// 直接打开下载
window.open()
2、post请求
- 若后端返回数据为
application/octet-stream格式
- application/octet-stream: 需要转成blob对象,在通过createObjectURL转成连接。
// res为后端返回的数据流
var blob = new Blob(['res'],{type:'application/vnd.ms-excel'})
var link = URL.createObjectURL(blob)
let a = document.createElement("a"); // 生成一个a元素
let event = new MouseEvent("click"); // 创建一个单击事件
a.download = "text.txt"; // 设置图片名称
a.href = link // 将生成的URL设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
- 若后端返回格式为
base64格式:可能需要我们拼接前缀,对应前缀如下。
-
文档 | 文件后缀 | 文档类型 | | -------- | -------- | | doc | data:application/msword;base64, | | docx | data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64, | | xls | data:application/vnd.ms-excel;base64, | | xlsx | data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64, | | pdf | data:application/pdf;base64, | | ppt | data:application/vnd.ms-powerpoint;base64, | | pptx | data:application/vnd.openxmlformats-officedocument.presentationml.presentation;base64, | | txt | data:text/plain;base64, |
-
图片 | 文件后缀 | 文档类型 | | -------- | -------- | | png | data:image/png;base64, | | jpg | data:image/jpeg;base64, | | gif | data:image/gif;base64, | | svg | data:image/svg+xml;base64, | | ico | data:image/x-icon;base64, | | bmp | data:image/bmp;base64, |
-
将拼接好的url通过a连接下载,代码如下!
a标签下载
let a = document.createElement("a"); // 生成一个a元素
let event = new MouseEvent("click"); // 创建一个单击事件
a.download = "text.txt"; // 设置图片名称
a.href = link // 将生成的base64设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
wondow.open()下载
windo.open()
二、Blob对象
1、第一个参数:ArrayBuffer、TypedArray、Blob、 DOMString:javascript里的string字符串 等对象构成的 Array,
- 为了让前端操作二进制数据才有了
ArrayBuffer、TypedArray、Uint8Array...等对象, 那他们分别代表什么意思呢? ArrayBuffer
官网解释:二进制数据缓冲区,它是一个字节数组。 个人理解为:无法读取和操作的数据格式,只能看到他的长度看不到内容更别说来
操作此内容,【那我们来如何操作呢?就有了另外几个api】
// 定义长度为4的数据容器, 哈哈,这里只能看不能有任何操作!
var buffer = new ArrayBuffer(4)
TypedArray
这个更是一个
烟雾弹,TypedArray既不是全局变量也不是函数(所以休想在全局中访问到他),他是Uint8Array...等子类的实例化,当我们得到TypedArray实例后便可以轻松的使用他的api操作数据了。
// 定义长度为4的数据容器, 哈哈,这里只能看不能有任何操作!
var buffer = new ArrayBuffer(4)
// 得到TypedArray 这样我就可以操作上面的数据了。
var TypedArray = new Uint8Array(buffer);
TypedArray[0] = 32;
TypedArray[1] = 64;
Uint8Array
数组类型表示一个8位无符号整型数组,创建时内容被初始化为0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。
// 创建TypedArray实例
var TypedArray = new Uint8Array(object);
2、第二个参数:官方文档有说是MIME媒体类型,白话意思:"定义下载文件的后缀名"
3、blob是前端操作数据的核心对象,很多数据处理都需要他在中间做转换,如图!!!

- File对象大家都很熟悉,当我们通过
input框选择照片的时候, 可以抓取到file对象,当你在浏览器控制台中打开file对象时,会发现file的原型指向blob对象file并没有定义任何api,都是继承blob对象, 由此可见blob对象的重要性。
三、问题?
1、blob对象MIME参数可以定义后缀名,a标签的download也可以定义后缀名,哪个优先级更高?
download的优先级更高 download没有定义后缀名的时候以MIME为准
var blob = new Blob(['1111'],{type:'application/vnd.ms-excel'}) //定义了exce表格
a.download = "text.txt"; // 定义了txt文本
2、改变后缀名文件大小是否被改变?
如下分别定义了
text.jpg、vscode.png、text.text三种不同的名字,转成了我想要的格式,但是他的数据大小是不会被改变的
四、实际开发应用
1、图片连接不在同一个域下,如何实现下载?
- 我们需要吧连接转成barse64然后在下载
- barse64可以用canvas的drawImage转成baser64,drawImage的参数是img
- 所以我们需要把url连接变成image对象。 代码如下!!
var img = new Image();
img.crossOrigin = 'anonymous'
img.src = '.....';
img.onload = function() {
let canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
let content = canvas.getContext('2d');
content.drawImage(img,0,0,img.width,img.height);
let url = canvas.toDataURL();
windo.open(url)
}
2、如何实现input框手动输入内容,并下载?
- 第一想到(a连接、window.open)实现下载,那么如何将a连接的href指向内容呢?
- 可能想到了用 URL.createObjectURL()创建连接,但是该函数的参数只能是 blob\file对象
- blob对象只要new一个即可,将我们要输入的文本以参数的形式传递进去,实例化一个blob对象。
- 通过以上想法,便可以实现这个功能。 代码如下! 有俩种可实行方案。
let text = document.getElementById("text");
let download = document.getElementById("download");
text.addEventListener('input', function() {
console.log(this.value)
})
download.addEventListener('click', function() {
var blob = new Blob(['1111'],{type:'application/vnd.ms-excel'})
console.log(blob);
let a = document.createElement("a"); // 生成一个a元素
let event = new MouseEvent("click"); // 创建一个单击事件
a.download = "text.txt"; // 设置图片名称
a.href = link // 将生成的URL设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
})
3、如何实现base64转成blob?
new Blob(array,options), 思考:从base64中获取Blob中获取俩个参数,如果获取到直接new一下就完美解决!!!
- [获取第二个参数]]:MIME类型很好获取 => 可以从base64前缀中读取到。 | base64前缀 | MIME类型 | | ---- | ---- | | data:application/msword;base64, | application/msword | | data:application/vnd.ms-powerpoint;base64, | application/vnd.ms-powerpoint |
代码如下
// mime类型
var mimeType = base64URI.split(',')[0].split(':')[1].split(';')[0];
- [获取第一个参数]:将base64内容转成TypeArray
解码base64-api:atob、编码base64-api:btoa、charCodeAt
function base64ToBlob() {
// mime类型
var mimeType = base64URI.split(',')[0].split(':')[1].split(';')[0];
// 解码base64
var atobBase64 = atob(base64URI.split(',')[1]); //base64 解码
// 创建二进制缓冲区,只能看不能操作
var arrayBuffer = new ArrayBuffer(atobBase64.length);
// 创建可以操作视图缓冲区数据的函数api - 只有这样才可以操作数据。
var typeArray01 = new Uint8Array(arrayBuffer)
// 操作类型数组,将解码barse64数据插入类数组中。
for (var i = 0; i < atobBase64.length; i++) {
typeArray01[i] = atobBase64.charCodeAt(i);
}
new Blob([typeArray01], {type: mimeType});
}
4、如何实现blob转成base64?
var reader = new FileReader();
reader.onload = function (e) {
callback(e.target.result);
}
reader.readAsDataURL(blob);
// application/vnd.openxmlformats-officedocument.wordprocessingml.document
