文件流的转换与下载
# 使用createObjectURL遇到的问题
# 在chrome中的表现
blob:http://172.28.74.136:8019/c2c5811e-906b-48d1-93a8-edb89c237f54
# 在IE中的表现
blob:9C9B0F3D-3E46-46F3-95AF-524089FB5E0F
# 第一时间想到的时候,createObjectURL这个属性的兼容问题,在ie中生成的链接不一样,于是决定手动去拼接一个和chrome一样的地址
# blob:${window.location.origin}/${URL.createObjectURL(blob).split(':')[1]}
结果遇到了另外一个坑,window.location.origin在IE中的结果是Undefined。。。换种方式拼接
# blob:${window.location.protocol}//${window.location.host}/${URL.createObjectURL(blob).split(':')[1]}
难受的是拼好也没用,在IE中,这样的方式也无法下载文件,于是乎,谷歌搜索。
# 解决方式
window.navigator.msSaveOrOpenBlob(blob, filename)
# 文件流
# 文件流相关接口
- 内置文件流接口:Blob (opens new window)(文件流接口定义)
- 内置文件流对象 :File (opens new window)(单文件,继承于接口Blob,故可使用Blod的方法级)和 FileList(多文件集合)
- 内置文件流读取对象 :FileReader (opens new window)(单文件读取)
# 文件流转换
# 1、file转base64
/**
* 上传附件转base64
* @param {File} file 文件流
*/
export const fileByBase64 = (file, callback) => {
var reader = new FileReader();
// 传入一个参数对象即可得到基于该参数对象的文本内容
reader.readAsDataURL(file);
reader.onload = function (e) {
// target.result 该属性表示目标对象的DataURL
console.log(e.target.result);
callback(e.target.result)
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 2、base64转blob
/**
* base64转Blob
* @param {*} data
*/
export const base64ByBlob = (base64, callback) => {
var arr = base64.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
console.log(new Blob([u8arr], { type: mime }))
callback(new Blob([u8arr], { type: mime }))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 3、blob转url
var url = window.URL.createObjectURL(blob)
1
# 4、使用demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文件流的转换与下载</title>
</head>
<body>
<input type="file" id="input"/>
</body>
<script>
const input = document.querySelector("input");
input.addEventListener("input", inputChanged);
function inputChanged(e) {
console.log(e.target.files[0], "files");
fileByBase64(e.target.files[0], () => {});
// fileByBase64(e.target.files[0], base64ByBlob);
}
const fileByBase64 = (file, callback) => {
var reader = new FileReader();
// 传入一个参数对象即可得到基于该参数对象的文本内容
reader.readAsDataURL(file);
reader.onload = function (e) {
// target.result 该属性表示目标对象的DataURL
console.log(e.target.result, "fileByBase64");
callback(e.target.result);
};
};
const base64ByBlob = (base64) => {
var arr = base64.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
const blob = new Blob([u8arr], { type: mime });
console.log(blob, "base64ByBlob");
// console.log(window.URL.createObjectURL(blob), "URL");
// downloadByFile(blob);
// callback(new Blob([u8arr], { type: mime }));
};
const downloadByFile = (blob) => {
// 创建a标签
const alink = document.createElement("a");
// 文件名
alink.download = "backup.txt";
// 开始下载
alink.style.display = "none";
// for IE
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, "backup.txt");
} else {
// for No-IE
alink.href = URL.createObjectURL(blob);
document.body.appendChild(alink);
// 触发点击a标签事件
alink.click();
document.body.removeChild(alink);
}
};
</script>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 文件下载
import axios from 'axios';
import request from '@/utils/request';
axios.defaults.timeout = 1000 * 60 * 5;
// 取response中的文件名称
const getFileNameFromHeader = headers => {
if (!headers) {
return '';
}
const contentDisposition = headers['content-disposition'];
if (!contentDisposition) {
return '';
}
const reg = /filename=(.*)/;
const result = reg.exec(contentDisposition);
return result ? decodeURI(result[1]) : '';
};
export default {
// 下载文件, 传入文件流
downloadByFile (res) {
// 处理返回的文件流
const content = res.data;
const headers = res.headers;
// 创建a标签
const alink = document.createElement('a');
// 文件名
alink.download = getFileNameFromHeader(headers);
// 开始下载
alink.style.display = 'none';
const blob = new Blob([content]);
// for IE
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, getFileNameFromHeader(headers));
} else {
// for No-IE
alink.href = URL.createObjectURL(blob);
document.body.appendChild(alink);
// 触发点击a标签事件
alink.click();
document.body.removeChild(alink);
}
},
// 下载文件, 传入接口名
downloadByUrl (exportParams) {
return new Promise(async (resolve, reject) => {
const {
url,
params,
fileName,
method
} = exportParams;
const requestParams = {
url: url,
method: method || 'get',
responseType: 'blob'
};
// 接口请求方式
if (method === 'post') {
requestParams.data = params;
} else {
requestParams.params = params;
}
try {
const res = await request(requestParams);
// 请求成功
resolve(res);
// 处理返回的文件流
const content = res.data;
const headers = res.headers;
// 创建a标签
const alink = document.createElement('a');
// 文件名
if (fileName) {
alink.download = fileName;
} else {
alink.download = getFileNameFromHeader(headers);
}
// 开始下载
alink.style.display = 'none';
const blob = new Blob([content]);
// for IE
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, getFileNameFromHeader(headers));
} else {
// for No-IE
alink.href = URL.createObjectURL(blob);
document.body.appendChild(alink);
// 触发点击a标签事件
alink.click();
document.body.removeChild(alink);
}
} catch (err) {
reject(err);
}
});
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# 大文件上传 与 断点续传
- 大文件上传基本都是分片,Blob.slice
- 断点续传:根据文件内容生成hash作为分片的名称,然后和服务端比对,上传过的不再上传。
参考这篇文章,讲的很清楚 :字节跳动面试官:请你实现一个大文件上传和断点续传 (opens new window)
# 参考
最近更新时间: 2021/06/17 10:13:36
- 01
- 2023/07/03 00:00:00
- 02
- 2023/04/22 00:00:00
- 03
- 2023/02/16 00:00:00