一、学习目标😀
- 了解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;functiondownLoad(){var blob =newBlob(["Hello, world!"],{ type:"text/plain;charset=utf-8"});debuggersaveAs(blob,"hello world.txt");//aNode.dispatchEvent(new MouseEvent("click"));}</script></html>
2、src目录结构
3、在浏览器打开test.html,点击下载按钮,进行代码调试
进入saveAs函数后可按下一步进行调试,查看代码执行过程。
fileSaver.js核心代码实现
varsaveAs=function(blob, name, opts){varURL= _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);// 40sclick(a);}};
4、fileSaver强大的一个点在于它兼容了主流的浏览器,下面是我的简易复刻版,省略了对浏览器兼容性考虑,
/**
* 仿写FileSaver.js文件保存方法
*/functioncorsEnabled(url){var xhr =newXMLHttpRequest();// 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方法functionclick(node){try{//dispatchEvent向指定事件目标派发Event
node.dispatchEvent(newMouseEvent("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()只能创建鼠标事件对象}functiondownload(url, name, opts){var xhr =newXMLHttpRequest();
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;constsaveAs=function(blob, name, opts){varURL= _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);// 方法二vargetGlobal=function(){if(typeof self !=='undefined'){return self;}if(typeof window !=='undefined'){return window;}if(typeof global !=='undefined'){return global;}thrownewError('unable to locate global object');};
四、在Vue中使用导出文件😊
导出不同的文件使用的MIME类型也不同
import{ message }from'ant-design-vue';// 导出文件 ,如果二进制数据是后端返回,须在axios添加请求参数 responseType: "blob"exportconstexportFileFun=function(res, name,type='application/vnd.ms-excel',fileSuffix='.xlsx'){let blob =newBlob([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
——
版权归原作者 徐小三 所有, 如有侵权,请联系我们删除。