FileSaver.js is a JavaScript library that allows you to save files on the client-side, directly from the user’s web browser. It provides a simple and consistent API for saving files of various types, bypassing the browser’s often inconsistent and limited native file download mechanisms. This means you can programmatically trigger a file download without relying on <a>
tags or form submissions.
Cross-browser consistency: FileSaver.js provides a unified API across different browsers, abstracting away the variations in how they handle file downloads. This simplifies your code and ensures consistent behavior across various platforms.
Programmatic control: You have complete control over the file download process, including the filename, file content, and MIME type. This is particularly useful for dynamically generated files or complex data processing workflows.
Enhanced user experience: FileSaver.js enables a smoother and more intuitive file download experience for users. It avoids the limitations and quirks often associated with older, less reliable methods.
Ease of use: The API is straightforward and easy to integrate into your existing JavaScript projects.
FileSaver.js supports a wide range of modern browsers, including:
For older browsers that lack the necessary features, FileSaver.js gracefully degrades, often using a fallback mechanism to provide the functionality. Check the official repository for the most up-to-date compatibility information. It’s generally compatible with any browser that supports Blob objects.
FileSaver.js can be easily installed using various methods:
npm: If you’re using npm (Node Package Manager), you can install it via the command line:
npm install file-saver
Then, import it into your JavaScript file:
import { saveAs } from 'file-saver';
CDN: You can include FileSaver.js directly from a CDN, such as jsDelivr:
<script src="https://cdn.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js"></script>
This will make the saveAs
function globally available.
Direct Download: Download the library from the official GitHub repository and include it in your project using a <script>
tag. Remember to reference the correct file path.
The simplest way to use FileSaver.js is to save a plain text file. This example saves a text string as a .txt
file:
import { saveAs } from 'file-saver';
const textToSave = 'Hello, FileSaver.js!';
const blob = new Blob([textToSave], { type: 'text/plain;charset=utf-8' });
saveAs(blob, 'my-file.txt');
This code first creates a Blob
object from the text string, specifying the MIME type as text/plain
. Then, it uses the saveAs
function to initiate the download, providing the Blob
and the desired filename.
FileSaver.js primarily works with Blob
objects. A Blob
represents a file-like object in the browser. You can create a Blob
from various data sources, including strings, arrays, and array buffers. This example demonstrates saving a Blob created from an array of strings:
import { saveAs } from 'file-saver';
const data = [
'Line 1',
'Line 2',
'Line 3'
;
]const blob = new Blob(data, { type: 'text/plain;charset=utf-8' });
saveAs(blob, 'my-data.txt');
Remember to specify the appropriate MIME type based on the content of your Blob.
The second argument to the saveAs
function determines the filename. You can use any valid filename, including extensions:
import { saveAs } from 'file-saver';
const blob = new Blob(['This is my file content.'], { type: 'text/plain;charset=utf-8' });
saveAs(blob, 'my-document.txt'); //Saves as my-document.txt
The filename should include the desired extension to indicate the file type to the user’s operating system.
The file type is crucial and is set using the type
property within the Blob
constructor. This determines how the browser handles the downloaded file (e.g., which application opens it). The filename extension should generally correspond to the MIME type.
import { saveAs } from 'file-saver';
//Save a CSV file
const csvData = 'Name,Age,City\nJohn,30,New York\nJane,25,London';
const blob = new Blob([csvData], { type: 'text/csv;charset=utf-8' });
saveAs(blob, 'my-data.csv');
// Save a JSON file
const jsonData = JSON.stringify({ name: 'John Doe', age: 30 });
const jsonBlob = new Blob([jsonData], { type: 'application/json;charset=utf-8' });
saveAs(jsonBlob, 'data.json');
Incorrect MIME types can lead to the file not opening correctly or being handled unexpectedly by the browser. Make sure to use the correct MIME type for the data you’re saving.
You can save files from data URLs using FileSaver.js. First, you need to convert the data URL into a Blob
:
import { saveAs } from 'file-saver';
function dataURLtoBlob(dataurl) {
let arr = dataurl.split(','),
= arr[0].match(/:(.*?);/)[1],
mime = atob(arr[1]),
bstr = bstr.length,
n = new Uint8Array(n);
u8arr
while(n--){
= bstr.charCodeAt(n);
u8arr[n]
}
return new Blob([u8arr], {type:mime});
}
const dataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
const blob = dataURLtoBlob(dataUrl);
saveAs(blob, 'image-from-dataurl.png');
This example defines a helper function dataURLtoBlob
to perform the conversion before passing the resulting Blob
to saveAs
.
To save the contents of a canvas element, you first need to get the image data as a data URL using canvas.toDataURL()
, and then use the dataURLtoBlob
function from the previous example:
import { saveAs } from 'file-saver';
// Assuming you have a canvas element with id 'myCanvas'
const canvas = document.getElementById('myCanvas');
const dataUrl = canvas.toDataURL();
const blob = dataURLtoBlob(dataUrl);
saveAs(blob, 'my-canvas.png');
Remember to replace 'myCanvas'
with the actual ID of your canvas element.
While FileSaver.js generally handles the download process smoothly, you might want to handle potential issues. Although errors are rare, you can wrap the saveAs
call in a try...catch
block:
import { saveAs } from 'file-saver';
try {
const blob = new Blob(['My file content'], {type: 'text/plain'});
saveAs(blob, 'my-file.txt');
catch (error) {
} console.error('Error saving file:', error);
// Add user-friendly error handling here, e.g., display an alert message.
}
This improves robustness by providing a mechanism for handling unexpected problems.
FileSaver.js doesn’t directly provide options to extensively customize the browser’s save dialog. The dialog’s appearance and behavior are primarily controlled by the browser itself. However, ensuring correct MIME types and filenames gives the user the best chance of a smooth experience.
FileSaver.js works seamlessly with various file types. The key is to use the appropriate MIME type when creating the Blob
:
import { saveAs } from 'file-saver';
// PDF
const pdfBlob = new Blob([pdfDocumentData], {type: 'application/pdf'}); //Replace pdfDocumentData with your PDF data
saveAs(pdfBlob, 'my-document.pdf');
// Image (assuming you have image data as a Uint8Array)
const imageBlob = new Blob([imageData], {type: 'image/jpeg'});
saveAs(imageBlob, 'my-image.jpg');
Remember that the pdfDocumentData
and imageData
placeholders must be replaced with your actual data.
The saveAs
function is asynchronous. While it doesn’t use Promises directly, the download process happens in the background. This means your code will continue executing after calling saveAs
without waiting for the download to complete. This behavior is usually desirable; however, if you need to know when the download finishes, consider using events provided by the browser (which are outside the scope of FileSaver.js itself). For example, you could check the download progress via browser dev tools’ network tab.
saveAs()
method parameters and return valuesThe core function of FileSaver.js is saveAs()
. It takes two parameters:
saveAs(blob, filename, [options]);
blob
: A Blob
object representing the file data to be saved. This is a required parameter.filename
: A string specifying the desired filename for the downloaded file. This includes the file extension (e.g., “my-file.txt”). This is a required parameter.options
: (Optional) An object containing additional options. Currently, FileSaver.js does not directly support options via this parameter, though future versions might.The saveAs()
function itself doesn’t return any value. The download process happens asynchronously in the background.
blob
(Required): This parameter is a Blob
object. A Blob is a file-like object representing raw data. You create a Blob
using the Blob
constructor, providing an array of data (e.g., strings, ArrayBuffers, etc.) and an optional type
property to specify the MIME type. The type
property is crucial for correctly identifying the file type and enabling the browser to handle the download appropriately. Examples of valid MIME types include: text/plain
, text/csv
, application/json
, image/png
, image/jpeg
, application/pdf
.
filename
(Required): This parameter is a string that determines the name of the downloaded file. It’s a user-friendly name and should typically include the appropriate file extension (e.g., .txt
, .csv
, .pdf
, .jpg
). The browser will use this filename to present the file download to the user.
options
(Optional): Currently, the options
parameter is not actively used by FileSaver.js. However, it’s included in the function signature for potential future extensions and to maintain consistency with other file handling APIs.
FileSaver.js generally handles the file saving process robustly. However, errors can occur due to issues like browser limitations or incorrect usage. While FileSaver.js doesn’t throw specific exceptions itself, problems might manifest as the file download failing to initiate or the save dialog not appearing. Therefore, good practice involves wrapping the saveAs
call in a try...catch
block to handle potential errors:
import { saveAs } from 'file-saver';
try {
const blob = new Blob(['My file content'], {type: 'text/plain'});
saveAs(blob, 'my-file.txt');
catch (error) {
} console.error('An error occurred while saving the file:', error);
// Add user-friendly error handling here (e.g., display an alert to the user).
}
This approach allows for better error management and provides a way to gracefully handle situations where the file saving operation fails. Note that the error
object might not always contain detailed information about the failure, especially in older browser versions. In such cases, error handling should primarily focus on preventing the application from crashing and providing feedback to the user.
This example demonstrates saving a simple text file:
import { saveAs } from 'file-saver';
const text = "This is the content of my text file.";
const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
saveAs(blob, 'my-text-file.txt');
To save an image file, you’ll typically start with image data (e.g., from a canvas element or a data URL). This example assumes you have image data as a Uint8Array:
import { saveAs } from 'file-saver';
// Replace 'imageData' with your actual image data (Uint8Array)
const imageData = new Uint8Array([/* ... your image data ... */]);
const blob = new Blob([imageData], { type: 'image/jpeg' });
saveAs(blob, 'my-image.jpg');
This example saves a CSV file with comma-separated values:
import { saveAs } from 'file-saver';
const csvData = "Name,Age,City\nJohn Doe,30,New York\nJane Doe,25,London";
const blob = new Blob([csvData], { type: 'text/csv;charset=utf-8' });
saveAs(blob, 'my-data.csv');
Saving JSON data involves creating a Blob from a JSON string:
import { saveAs } from 'file-saver';
const jsonData = JSON.stringify({ name: "John Doe", age: 30, city: "New York" });
const blob = new Blob([jsonData], { type: 'application/json;charset=utf-8' });
saveAs(blob, 'my-data.json');
This example demonstrates combining data from different sources into a single downloadable file (a zip archive in this case). Note that this requires a library to create the zip archive; this is just illustrative and you would need to include a suitable library like JSZip.
import { saveAs } from 'file-saver';
import JSZip from 'jszip'; // You'll need to install jszip: npm install jszip
async function saveCombinedData() {
const zip = new JSZip();
// Add text file
.file("data.txt", "This is some text data.");
zip
// Add JSON data
.file("data.json", JSON.stringify({ a: 1, b: 2 }));
zip
// Assuming you have image data as a Uint8Array
const imageData = new Uint8Array([/* ... your image data ... */]);
.file("image.jpg", imageData, {binary:true});
zip
const content = await zip.generateAsync({ type: "blob" });
saveAs(content, "combined_data.zip");
}
saveCombinedData();
This advanced example shows how FileSaver.js integrates with other libraries to handle more complex file types and data combinations. Remember to replace placeholder data with your actual data and install the necessary libraries.
“TypeError: Failed to execute ‘saveAs’ on ‘FileWriter’: parameter 1 is not of type ‘Blob’.” This error indicates that you’re not passing a Blob
object as the first argument to saveAs()
. Double-check that you’ve correctly created a Blob
using the Blob
constructor and that the variable you’re passing is indeed a Blob
instance.
File doesn’t download or opens incorrectly: This is often due to an incorrect MIME type specified in the Blob
constructor. Ensure you use a MIME type that accurately represents the file’s content (e.g., text/plain
, application/json
, image/png
, application/pdf
). Inconsistencies between the file extension in the filename and the MIME type can also cause this issue.
Browser doesn’t support FileSaver.js: While FileSaver.js has wide browser compatibility, extremely old or unsupported browsers might lack the necessary features. Test on your target browsers and consider providing graceful fallback mechanisms if necessary. FileSaver.js typically degrades gracefully for unsupported features.
Security restrictions: In some cases, security policies in your browser or server might prevent file downloads. Check your browser’s security settings and ensure that the web server isn’t imposing restrictions.
Check the browser’s console: Open your browser’s developer console (usually by pressing F12) to look for JavaScript errors or warnings. These can often pinpoint the source of problems with FileSaver.js.
Inspect the Blob
object: Use your browser’s developer tools to inspect the Blob
object you’re passing to saveAs()
. Verify that it contains the expected data and that its type
property is correctly set.
Simplify the code: If you’re dealing with a complex scenario, try simplifying your code to isolate the problem. Create a minimal example that demonstrates the issue to help pinpoint the cause.
Test in different browsers: Test your code in multiple browsers (Chrome, Firefox, Edge, Safari) to see if the problem is browser-specific. This can help identify compatibility issues.
Although FileSaver.js aims for cross-browser compatibility, minor inconsistencies might exist. Here are some potential browser-specific considerations:
Older browsers: Older browsers might have limitations in how they handle Blob
objects or the file download process. FileSaver.js includes fallback mechanisms but may not fully support all features on older browsers.
Security contexts: The browser’s security context (e.g., whether the script is running in a secure HTTPS context) can influence the success of the file download. Ensure your website is served via HTTPS if you’re encountering download issues.
Extensions and add-ons: Browser extensions or add-ons can sometimes interfere with file downloads. Try disabling extensions to see if they are causing conflicts.
If you encounter persistent issues that don’t align with the common errors listed above, please provide detailed information about your setup, code snippet, browser, and observed behavior to facilitate more effective troubleshooting. Consulting the FileSaver.js GitHub repository’s issues section might also reveal solutions to previously encountered problems.
If you discover a bug in FileSaver.js, please report it on the project’s GitHub issue tracker. When reporting a bug, please provide the following information:
Clear and concise bug reports greatly assist in identifying and resolving issues efficiently.
If you have an idea for a new feature or improvement to FileSaver.js, please suggest it on the GitHub issue tracker. When suggesting a feature, explain:
Well-reasoned feature suggestions increase the likelihood of your proposal being considered and potentially included in future releases.
FileSaver.js follows a consistent coding style. If you contribute code, please adhere to the following guidelines:
Consistency in coding style improves code readability and maintainability.
FileSaver.js uses a testing framework (likely Jest or similar). If you’re contributing code, you’re expected to write unit tests to ensure the functionality and correctness of your changes. The project’s README
or CONTRIBUTING
file usually contains detailed instructions on how to set up the development environment and run the tests. Before submitting a pull request, thoroughly test your code to verify that it works correctly and doesn’t introduce regressions. Testing is essential for maintaining the quality and stability of FileSaver.js. Adhering to existing testing practices will help integrate your changes seamlessly.