Front-end export file | fileSaver.js source code reading

1. Learning objectives

  1. Understand the core implementation of fileSaver.js
  2. Do-it-yourself easy export
  3. How to use files in Vue

2. Source code debugging

1. fileSave.js library address: https://github.com/eligrey/FileSaver.js

1. git clone https://github.com/eligrey/FileSaver.js.git

2. cd FileSaver.js-master/src directory

3. Create a new test.html under src, copy the code below

<!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">Download</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 directory structure

111111.png

3. Open test.html in the browser, click the download button, and debug the code

image.png\

After entering the saveAs function, you can press the next step to debug and view the code execution process. image.png\

fileSaver.js core code implementation

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;
// handle string type binary
if (typeof blob === "string") {<!-- -->
//...
a.href = blob;
click(a); // Trigger the click method of the a anchor
} else {<!-- -->
// Process pictures, file types binary
a.href = URL.createObjectURL(blob);
setTimeout(function () {<!-- -->
URL.revokeObjectURL(a.href);
}, 4e4); // 40s
click(a);
}
};

4. One of the powerful points of fileSaver is that it is compatible with mainstream browsers. The following is my simple copy version, which omits the consideration of browser compatibility.

/**
 * Copy FileSaver.js file saving method
 */

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 & amp; & amp; xhr.status <= 299;
}

// Trigger the click method of the a anchor point
function click(node) {<!-- -->
try {<!-- -->
//dispatchEvent dispatches Event to the specified event target
node.dispatchEvent(new MouseEvent("click"));
} catch (e) {<!-- -->
// document.createEvent also creates an event object.
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() can create any type of event object, and the application scenario is more complex
//new MouseEvent() can only create mouse event objects
}
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();
}
// Initialize the environment and determine the top-level object
const_global =
typeof window !== "undefined" & amp; & amp; window.window === window
? window
: typeof self === "object" & amp; & amp; self.self === self
? self
: typeof global === "object" & amp; & amp; global.global === global
?global
: this;

const saveAs = function (blob, name, opts) {<!-- -->
var URL = _global.URL; // window.URL in browser
// document.createElementNS creates an element with the specified namespace URI and qualified name
//Create an element without specifying a namespace URI, use the createElement method
var a = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
name = name || blob.name || "download";

a.download = name;
a.rel = "noopener";

// string type binary
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 {<!-- -->
// Create a DOMString
a.href = URL.createObjectURL(blob);
setTimeout(function () {<!-- -->
URL.revokeObjectURL(a.href);
}, 4000);
setTimeout(function () {<!-- -->
click(a);
}, 0);
}
};

_global. saveAs = saveAs;

// Judging that the module is loaded, it is only applicable to the Node.js environment, and cannot be used on the browser side.
if (typeof module !== "undefined") {<!-- -->
module.exports = saveAs;
}

3. Summary

fileSaver.js mentions the globalThis object of ES6, here is a simple extension. There is a top-level object in the JavaScript language, which provides the global environment (that is, the global scope), and all code is run in this environment.
However, top-level objects are not uniform across implementations.

  • In the browser, the top-level object is window, but Node and Web Worker do not have windows.

  • In browsers and Web Workers, self also points to the top-level object, but Node does not have self.

  • In Node, the top-level object is global, but it is not supported in other environments.
    In order to be able to get the top-level object in various environments, the same piece of code now generally uses the this keyword, but there are limitations.

  • In the global environment, this returns the top-level object. However, in the Node.js module, this returns the current module, and in the ES6 module, this returns undefined.

  • The this in the function, if the function is not run as an object method, but simply as a function, this will point to the top-level object. However, in strict mode, this will return undefined at this time.

  • Regardless of whether it is strict mode or normal mode, new Function(‘return this’)() will always return the global object. However, if the browser uses CSP (Content Security Policy, Content Security Policy), then methods such as eval and new Function may not be available.
    Here’s how to get the top-level object

// method one
(typeof window !== 'undefined'
 ? window
 : (typeof process === 'object' & amp; & amp;
    typeof require === 'function' & amp; & amp;
    typeof global === 'object')
 ?global
 : this);

// Method Two
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');
};

4. Use export files in Vue

Different MIME types are used for exporting different files

import {<!-- --> message } from 'ant-design-vue';

// Export the file, if the binary data is returned by the backend, the request parameter responseType: "blob" must be added to axios
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('exported successfully')
}

3.1 List of common MIME types

extension document type MIME type
.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 code is not readable to normal users (RFC 3023, section 3) text/xml code is not readable to normal users Say readable (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 (if not included video)
.3g2 3GPP2 audio/video container video/3gpp2 audio/3gpp2 (if no video)
.7z 7-zip archive application/x-7z-compressed