FileSaver Source Code Analysis
·
2 min read
Web file download can use the mature library FileSaver.js, which is only 2KB after compression, so introducing it won’t be much of a size burden on the site. At the same time, we also need to understand the implementation of this package. Here we’ll organize the implementation logic.
saveAs API
First look at the parameters of the API method. You can see that you can directly pass in file data or URL.
FileSaver saveAs(Blob/File/Url, optional DOMString filename, optional Object { autoBom })
Processing Flow
- Manipulate DOM to create an anchor element. Since the anchor element has no content set, it won’t appear on the current page.
- Set the download attribute of the anchor element, with the value being the specified filename.
- Set the rel value of the anchor element to noopener, which benefits performance and security.
- Determine if the save storage is a string
- If it’s a string, it will be treated as a URL. Then, based on whether it’s cross-origin, decide whether to use the anchor tag for direct download and save. If cross-origin, the download attribute won’t work, so XHR must be used to download data and then save as blob. If not cross-origin, the anchor tag can directly hang the URL and download to ensure download and save.
- If it’s not a URL, the blob data is directly used as the href of the anchor element, and a.click() is triggered.
Download File Instead of Opening File
When we directly download files via URL, we’ll find that the browser will open the file by default. If we want to change this behavior, there are several ways:
- For same-origin file downloads, just set the download attribute in the anchor tag method. The browser will treat it as setting Content-Disposition:attachment, so it will download as an attachment.
- For non-same-origin file downloads, the download attribute won’t work, so you need to asynchronously download the file to get blob data, then construct an anchor tag to save, or have the server return with Content-Disposition:attachment set.
Prevent Memory Leaks
- You can notice that after the anchor element’s href is bound to objectURL, it will use setTimeout and then execute click download, followed by delayed execution of
URL.revokeObjectURL(a.href)
. This is mainly done to worry about memory leaks when files are too large, requiring manual memory cleanup. - Since the anchor element is not appended to document.body, there’s no manual deletion of the anchor element, so revoke is used here. If the anchor element were bound to document.body, this could actually be solved by deleting the element.
Final Thoughts
Done.