一、学习目标😀
- 了解fileSaver.js核心实现
- 自己动手实现简易导出功能
- 在Vue中如何使用文件
二、源码调试😊
1、fileSave.js库地址:https://github.com/eligrey/FileSaver.js
1、git clone https://github.com/eligrey/FileSaver.js.git
2、cd FileSaver.js-master/ src 目录
3、在src下新建test.html,copy 下面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button id="btn">下载</button>
<a href="www.baidu.com" class="anode"></a>
</body>
<script src="./FileSaver.js"></script>
<script>
console.log(window,'window')
const btn = document.querySelector("#btn");
const aNode = document.querySelector(".anode");
btn.onclick = downLoad;
function downLoad() {
var blob = new Blob(["Hello, world!"], { type: "text/plain;charset=utf-8" });
debugger
saveAs(blob, "hello world.txt");
//aNode.dispatchEvent(new MouseEvent("click"));
}
</script>
</html>
2、src目录结构
3、在浏览器打开test.html,点击下载按钮,进行代码调试
![image.png](https://i-blog.csdnimg.cn/blog_migrate/d7ccac758f11fbf970277c5f237a4d15.png)
进入saveAs函数后可按下一步进行调试,查看代码执行过程。
fileSaver.js核心代码实现
var saveAs = function (blob, name, opts) {
var URL = _global.URL || _global.webkitURL;
//...
var a = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
a.download = name;
// 处理字符串类型二进制
if (typeof blob === "string") {
//...
a.href = blob;
click(a); // 触发a锚点的click方法
} else {
// 处理图片、文件类型二进制
a.href = URL.createObjectURL(blob);
setTimeout(function () {
URL.revokeObjectURL(a.href);
}, 4e4); // 40s
click(a);
}
};
4、fileSaver强大的一个点在于它兼容了主流的浏览器,下面是我的简易复刻版,省略了对浏览器兼容性考虑,
/**
* 仿写FileSaver.js文件保存方法
*/
function corsEnabled(url) {
var xhr = new XMLHttpRequest();
// use sync to avoid popup blocker
xhr.open("HEAD", url, false);
try {
xhr.send();
} catch (e) {}
console.log(xhr.status,'status')
return xhr.status >= 200 && xhr.status <= 299;
}
// 触发a锚点的click方法
function click(node) {
try {
//dispatchEvent向指定事件目标派发Event
node.dispatchEvent(new MouseEvent("click"));
} catch (e) {
// document.createEvent也是创建事件对象。
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent(
"click",
true,
true,
window,
0,
0,
0,
80,
20,
false,
false,
false,
false,
0,
null
);
node.dispatchEvent(evt);
}
//createEvent()可以创建任何类型的事件对象,应用场景更复杂
//new MouseEvent()只能创建鼠标事件对象
}
function download(url, name, opts) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = "blob";
xhr.onload = function () {
saveAs(xhr.response, name, opts);
};
xhr.onerror = function () {
console.error("could not download file");
};
xhr.send();
}
// 初始化环境,判断顶层对象
const _global =
typeof window !== "undefined" && window.window === window
? window
: typeof self === "object" && self.self === self
? self
: typeof global === "object" && global.global === global
? global
: this;
const saveAs = function (blob, name, opts) {
var URL = _global.URL; // 浏览器中 window.URL
// document.createElementNS 创建一个具有指定命名空间 URI 和限定名称的元素
//创建一个元素而不指定命名空间URI,可使用createElement方法
var a = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
name = name || blob.name || "download";
a.download = name;
a.rel = "noopener";
// 字符串类型二进制
if (typeof blob === "string") {
a.href = blob;
if (a.origin !== location.origin) {
corsEnabled(a.href) ? download(blob, name, opts) : click(a, (a.target = "_blank"));
} else {
click(a);
}
} else {
// 创建一个DOMString
a.href = URL.createObjectURL(blob);
setTimeout(function () {
URL.revokeObjectURL(a.href);
}, 4000);
setTimeout(function () {
click(a);
}, 0);
}
};
_global.saveAs = saveAs;
// 判断模块被加载,只适用于Node.js环境中,并不能在浏览器端使用。
if (typeof module !== "undefined") {
module.exports = saveAs;
}
三、小结😳
fileSaver.js提到ES6的globalThis对象,这里简单扩展下。JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。
但是,顶层对象在各种实现里面是不统一的。
-
浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。
-
浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。
-
Node 里面,顶层对象是global,但其他环境都不支持。
同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this关键字,但是有局限性。 -
全局环境中,this会返回顶层对象。但是,Node.js 模块中this返回的是当前模块,ES6 模块中this返回的是undefined。
-
函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。
-
不管是严格模式,还是普通模式,new Function(‘return this’)(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。
下面是获取顶层对象的方法
// 方法一
(typeof window !== 'undefined'
? window
: (typeof process === 'object' &&
typeof require === 'function' &&
typeof global === 'object')
? global
: this);
// 方法二
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
四、在Vue中使用导出文件😊
导出不同的文件使用的MIME类型也不同
import { message } from 'ant-design-vue';
// 导出文件 ,如果二进制数据是后端返回,须在axios添加请求参数 responseType: "blob"
export const exportFileFun = function (res, name,type='application/vnd.ms-excel',fileSuffix='.xlsx') {
let blob = new Blob([res], {
type,
})
let fileName = name + fileSuffix
let link = document.createElement('a')
link.download = fileName
link.href = window.URL.createObjectURL(blob)
document.body.appendChild(link)
link.click()
setTimeout(() => {
window.URL.revokeObjectURL(link.href)
},1000)
message.success('导出成功')
}
3.1常见 MIME 类型列表
扩展名 | 文档类型 | MIME 类型 | |
---|---|---|---|
.aac | AAC audio | audio/aac | |
.abw | AbiWord document | application/x-abiword | |
.arc | Archive document (multiple files embedded) | application/x-freearc | |
.avi | AVI: Audio Video Interleave | video/x-msvideo | |
.azw | Amazon Kindle eBook format | application/vnd.amazon.ebook | |
.bin | Any kind of binary data | application/octet-stream | |
.bmp | Windows OS/2 Bitmap Graphics | image/bmp | |
.bz | BZip archive | application/x-bzip | |
.bz2 | BZip2 archive | application/x-bzip2 | |
.csh | C-Shell script | application/x-csh | |
.css | Cascading Style Sheets (CSS) | text/css | |
.csv | Comma-separated values (CSV) | text/csv | |
.doc | Microsoft Word | application/msword | |
.docx | Microsoft Word (OpenXML) | application/vnd.openxmlformats-officedocument.wordprocessingml.document | |
.eot | MS Embedded OpenType fonts | application/vnd.ms-fontobject | |
.epub | Electronic publication (EPUB) | application/epub+zip | |
.gif | Graphics Interchange Format (GIF) | image/gif | |
.htm .html | HyperText Markup Language (HTML) | text/html | |
.ico | Icon format | image/vnd.microsoft.icon | |
.ics | iCalendar format | text/calendar | |
.jar | Java Archive (JAR) | application/java-archive | |
.jpeg .jpg | JPEG images | image/jpeg | |
.js | JavaScript | text/javascript | |
.json | JSON format | application/json | |
.jsonld | JSON-LD format | application/ld+json | |
.mid .midi | Musical Instrument Digital Interface (MIDI) | audio/midi audio/x-midi | |
.mjs | JavaScript module | text/javascript | |
.mp3 | MP3 audio | audio/mpeg | |
.mpeg | MPEG Video | video/mpeg | |
.mpkg | Apple Installer Package | application/vnd.apple.installer+xml | |
.odp | OpenDocument presentation document | application/vnd.oasis.opendocument.presentation | |
.ods | OpenDocument spreadsheet document | application/vnd.oasis.opendocument.spreadsheet | |
.odt | OpenDocument text document | application/vnd.oasis.opendocument.text | |
.oga | OGG audio | audio/ogg | |
.ogv | OGG video | video/ogg | |
.ogx | OGG | application/ogg | |
.otf | OpenType font | font/otf | |
.png | Portable Network Graphics | image/png | |
.pdf | Adobe Portable Document Format (PDF) | application/pdf | |
.ppt | Microsoft PowerPoint | application/vnd.ms-powerpoint | |
.pptx | Microsoft PowerPoint (OpenXML) | application/vnd.openxmlformats-officedocument.presentationml.presentation | |
.rar | RAR archive | application/x-rar-compressed | |
.rtf | Rich Text Format (RTF) | application/rtf | |
.sh | Bourne shell script | application/x-sh | |
.svg | Scalable Vector Graphics (SVG) | image/svg+xml | |
.swf | Small web format (SWF) or Adobe Flash document | application/x-shockwave-flash | |
.tar | Tape Archive (TAR) | application/x-tar | |
.tif .tiff | Tagged Image File Format (TIFF) | image/tiff | |
.ttf | TrueType Font | font/ttf | |
.txt | Text, (generally ASCII or ISO 8859-n) | text/plain | |
.vsd | Microsoft Visio | application/vnd.visio | |
.wav | Waveform Audio Format | audio/wav | |
.weba | WEBM audio | audio/webm | |
.webm | WEBM video | video/webm | |
.webp | WEBP image | image/webp | |
.woff | Web Open Font Format (WOFF) | font/woff | |
.woff2 | Web Open Font Format (WOFF) | font/woff2 | |
.xhtml | XHTML | application/xhtml+xml | |
.xls | Microsoft Excel | application/vnd.ms-excel | |
.xlsx | Microsoft Excel (OpenXML) | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | |
.xml | XML | application/xml 代码对普通用户来说不可读 (RFC 3023, section 3) text/xml 代码对普通用户来说可读 (RFC 3023, section 3) | |
.xul | XUL | application/vnd.mozilla.xul+xml | |
.zip | ZIP archive | application/zip | |
.3gp | 3GPP audio/video container | video/3gpp audio/3gpp (若不含视频) | |
.3g2 | 3GPP2 audio/video container | video/3gpp2 audio/3gpp2 (若不含视频) | |
.7z | 7-zip archive | application/x-7z-compressed | |
— | — | ||