一、前言
这两天在开发过程中遇到下载图片的需求,没想到常规的写法无法下载,只能在浏览器打开,之前还真没没注意过,思考下最近做的关于文件操作的内容,做下总结。
- 下载媒体资源
- 上传媒体(图片、音频、视频)到云存储
- 本地解析媒体资源
- Base64位转码给后端保存
二、关于前端文件下载
前端几种常见的下载文件的方法
- 1、a标签
- 2、js
- 3、window.open
需要注意是的,a标签对于跨域的资源是有不同表现的。
- 当下载资源和当前资源跨域,且当前资源可以直接在浏览器打开预览(比如图片、PDF)将无法下载,会在浏览器打开,解决方法在后面
- 当下载资源和当前资源跨域,且资源浏览器无法预览(比如XLSX)将会下载该文件
- 不跨域的情况下将会下载
1、a标签
大部分文件都可以用a标签+download属性
来下载,简单方便。
html
<a href="path/to/file.pdf" download="filename.pdf">点击下载文件</a>
2、js下载文件
js下载文件也是通过创建a标签来实现的,对比a标签的下载更灵活。
js
export const downloadFile = ({
fileUrl,
fileName,
callback
}:{
fileUrl: string,
fileName: string,
callback?: (error?:any) => void
}) => {
try {
const url = fileUrl;
const link = document.createElement('a');
link.target = '_blank';
link.style.display = 'none';
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
callback && callback();
} catch (err) {
callback && callback(err);
}
};
因为JS也是通过创建A标签来实现的,所以需要先拉取Blob格式的资源,然后创建本地域名一致的资源URL,再进行下载
js
export const downloadCorsFile = ({
fileUrl,
fileName,
callback
}:{
fileUrl: string,
fileName: string,
callback?: (error?:any) => void
}) => {
try {
// 也可以使用fetch拉取资源,不过要注意兼容性
const xhr = new XMLHttpRequest();
xhr.open('get', fileUrl, true);
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function (res) {
const url = window.URL.createObjectURL(res.target.response);
downloadFile({url, fileName, callback});
};
} catch (err) {
callback(err);
}
};
3、利用浏览器行为下载
window.open
和window.location.href
是利用浏览器对应的URL就会将文件下载下来。可以用来下载XLSX、ZIP文件等。
js
window.open('https://demo/download_filename.xlsx', '_blank')
window.location.href = 'https://demo/download_filename.xlsx'
三、文件转化成Base64位
1、File或Blob类型转化成base64位
在开发中,我们常常要将文件转化成base64位,文件可能是手动上传的文件、通过URL下载的图片等。
原理都是通过FileReader
对象,调用实例方法readAsDataURL
将文件读取为Base64位。
js
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
const result = reader.result;
}
由于异步获取的base64位,为了方便使用,我们常常通过Promise处理下
js
// File/Blob转化成base64位
export function fileToBase64(file: File | Blob): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
const result = reader.result;
resolve(result);
};
reader.onerror = reject;
});
}
2、通过URL获取文件的类型,然后将Blob转化成base64位
js
export function urlToBase64(url) {
return fetch(url)
.then((response) => response.blob())
.then((blob) => {
return fileToBase64(blob)
});
}
FileReader对象的几种常见方法包括:
readAsBinaryString(Blob or File)
:将输入的 Blob 或 File 对象读取为二进制字符串。readAsArrayBuffer(Blob or File)
:将输入的 Blob 或 File 对象读取为一个 ArrayBuffer。readAsDataURL(Blob or File)
:将输入的 Blob 或 File 对象读取为一个 Base64 编码的字符串。readAsText(Blob or File, encoding)
:将输入的 Blob 或 File 对象读取为一个文本字符串,其中第二个参数指定字符编码。