Using Data URLs to Save Files
The easiest way to save a file is to use Data URLs that include all the relevant information. These data URLs are special URLs that are prefixed with the
data: scheme. They are ideal for embedding small files in your HTML documents. These URLs follow the following syntax:
mediatype token is actually a MIME type that specifies the nature and format of a document or file. Its default value is
base64 token is optional and needed only when you want to store binary data textually. We specify our actual data after all these tokens.
We can use the
download attribute to specify the name of the file where we want to put all our content after download. Here is an example of using all these attributes together:
<a download="monty.txt" href=" name is Monty.">Download Text File with Name</a>
const link = document.querySelector('a.dynamic'); let name="Monty"; let text = `My name in $name. I love writing tutorials.`; link.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); link.setAttribute('download', `$name.toLowerCase().txt`);
We begin by selecting our link using the
querySelector() method and then create a bunch of variables to store the file name and its contents. Use of template literals allows us to work with multi-line strings easily.
We create our data URL by concatenating the meta data with the actual content encoded using the
Using Blobs to Create and Save Files
We can create our own blobs using the
Blob() constructor which accepts an array of specific objects to be put inside the blob. You can pass the MIME type of the data as key-value pair in an object that is the second parameter of the
Blob() constructor. It is an empty string by default.
const link = document.querySelector('a.simple'); let name="Monty"; let text = `My name in $name. I love writing tutorials.`; var textBlob = new Blob([text], type: 'text/plain'); link.setAttribute('href', URL.createObjectURL(textBlob)); link.setAttribute('download', `$name.toLowerCase().txt`);
We create our
textBlob by calling the
Blob() constructor and passing our
text variable to it as an array element. After that, we simply set the value of
download attributes. The URL in this case is created by calling the
createObjectURL() function which returns a string that contains the URL for the object that we passed to it.
Lets go a step further and create a blob where the text is obtained dynamically from a
textarea element on the webpage. You will be able to write anything you like in the
textarea and then click on the Save File button to save it as a file.
const saveBtn = document.querySelector('button.save-file'); let name="Monty"; saveBtn.addEventListener('click', function() var tempLink = document.createElement("a"); let textArea = document.querySelector("textarea"); var taBlob = new Blob([textArea.value], type: 'text/plain'); tempLink.setAttribute('href', URL.createObjectURL(taBlob)); tempLink.setAttribute('download', `$name.toLowerCase().txt`); tempLink.click(); URL.revokeObjectURL(tempLink.href); );
We begin by getting a reference to our button and then listening to its click events. Once the button is clicked, we get the value of our
textarea element and convert it to a blob. After that, we create a URL that references our blob and assign it to the
href attribute of the anchor tag that we created.
You can try it out in the following CodePen demo. As an exercise, try to modify the code so that that it saves the file with a name entered by the users instead of something static.
The reason a web developer is not allowed to have complete control over the location where a file is saved by the browser has to do with security. The internet would be a lot less secure if every website had access to the filesystem on your device. They could simply inject malicious code into your system or view private information.
Earlier, it wasn’t possible to save a file anywhere except the default download folder which was dictated by the browser’s setting and not individual websites. However, the File System Access API allows developers to suggest where a file can be saved after they have been granted access by the user. Keep in mind that the wider browser support is currently lacking for the API and the browsers which do support it only do it partially.
const saveBtn = document.querySelector('button.save-file'); let name="Monty"; saveBtn.addEventListener('click', async function() let textArea = document.querySelector("textarea"); var taBlob = new Blob([textArea.value], type: 'text/plain'); const pickerOptions = suggestedName: `$name.toLowerCase().txt`, types: [ description: 'Simple Text File', accept: 'text/plain': ['.txt'], , , ], ; const fileHandle = await window.showSaveFilePicker(pickerOptions); const writableFileStream = await fileHandle.createWritable(); await writableFileStream.write(taBlob); await writableFileStream.close(); );
As usual, we begin by creating a blob of the
text inside the
textarea element. We create an object that contains different options for our file picker that shows up when we call the
showFilePicker() method. We can suggest a name to save the file here and also pass an array of allowed file types to save. This method returns a
FileSystemFileHandle on which we can call the
createWritable() method creates a writable stream and we write the blob we created earlier to this stream. Finally, we close our writable stream. At this point, the content from the stream is saved to the file.
Try writing something in the
textarea of the following CodePen and then click on the Save File button. The demo will not work in Firefox so you should try using Chrome or Edge.
download attributes. The last technique involves use of the File System Access API and gives us better control over different aspects of the process like changing the default download location with user’s permission. However, it doesn’t currently have significant browser support to be used in real projects.