[javascript] JavaScript: Create and save file

I have data that I want to write to a file, and open a file dialog for the user to choose where to save the file. It would be great if it worked in all browsers, but it has to work in Chrome. I want to do this all client-side.

Basically I want to know what to put in this function:

saveFile: function(data)
{
}

Where the function takes in data, has the user select a location to save the file, and creates a file in that location with that data.

Using HTML is fine too, if that helps.

This question is related to javascript file dialog save

The answer is


StreamSaver is an alternative to save very large files without having to keep all data in the memory.
In fact it emulates everything the server dose when saving a file but all client side with service worker.

You can either get the writer and manually write Uint8Array's to it or pipe a binary readableStream to the writable stream

There is a few example showcasing:

  • How to save multiple files as a zip
  • piping a readableStream from eg Response or blob.stream() to StreamSaver
  • manually writing to the writable stream as you type something
  • or recoding a video/audio

Here is an example in it's simplest form:

const fileStream = streamSaver.createWriteStream('filename.txt')

new Response('StreamSaver is awesome').body
  .pipeTo(fileStream)
  .then(success, error)

If you want to save a blob you would just convert that to a readableStream

new Response(blob).body.pipeTo(...) // response hack
blob.stream().pipeTo(...) // feature reference

You cannot do this purely in Javascript. Javascript running on browsers does not have enough permission yet (there have been proposals) due to security reasons.

Instead, I would recommend using Downloadify:

A tiny javascript + Flash library that enables the creation and download of text files without server interaction.

You can see a simple demo here where you supply the content and can test out saving/cancelling/error handling functionality.


Tried this in the console, and it works.

var aFileParts = ['<a id="a"><b id="b">hey!</b></a>'];
var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // the blob
window.open(URL.createObjectURL(oMyBlob));

A very minor improvement of the code by Awesomeness01 (no need for anchor tag) with addition as suggested by trueimage (support for IE):

// Function to download data to a file
function download(data, filename, type) {
    var file = new Blob([data], {type: type});
    if (window.navigator.msSaveOrOpenBlob) // IE10+
        window.navigator.msSaveOrOpenBlob(file, filename);
    else { // Others
        var a = document.createElement("a"),
                url = URL.createObjectURL(file);
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        setTimeout(function() {
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);  
        }, 0); 
    }
}

Tested to be working properly in Chrome, FireFox and IE10.

In Safari, the data gets opened in a new tab and one would have to manually save this file.


For Chrome and Firefox, I have been using a purely JavaScript method.

(My application cannot make use of a package such as Blob.js because it is served from a special engine: a DSP with a WWWeb server crammed in and little room for anything at all.)

function FileSave(sourceText, fileIdentity) {
    var workElement = document.createElement("a");
    if ('download' in workElement) {
        workElement.href = "data:" + 'text/plain' + "charset=utf-8," + escape(sourceText);
        workElement.setAttribute("download", fileIdentity);
        document.body.appendChild(workElement);
        var eventMouse = document.createEvent("MouseEvents");
        eventMouse.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        workElement.dispatchEvent(eventMouse);
        document.body.removeChild(workElement);
    } else throw 'File saving not supported for this browser';
}

Notes, caveats, and weasel-words:

  • I have had success with this code in both Chrome and Firefox clients running in Linux (Maipo) and Windows (7 and 10) environments.
  • However, if sourceText is larger than a MB, Chrome sometimes (only sometimes) gets stuck in its own download without any failure indication; Firefox, so far, has not exhibited this behavior. The cause might be some blob limitation in Chrome. Frankly, I just don't know; if anybody has any ideas how to correct (or at least detect), please post. If the download anomaly occurs, when the Chrome browser is closed, it generates a diagnostic such as Chrome browser diagnostic
  • This code is not compatible with Edge or Internet Explorer; I have not tried Opera or Safari.

This project on github looks promising:

https://github.com/eligrey/FileSaver.js

FileSaver.js implements the W3C saveAs() FileSaver interface in browsers that do not natively support it.

Also have a look at the demo here:

http://eligrey.com/demos/FileSaver.js/


_x000D_
_x000D_
function download(text, name, type) {_x000D_
  var a = document.getElementById("a");_x000D_
  var file = new Blob([text], {type: type});_x000D_
  a.href = URL.createObjectURL(file);_x000D_
  a.download = name;_x000D_
}
_x000D_
<a href="" id="a">click here to download your file</a>_x000D_
<button onclick="download('file text', 'myfilename.txt', 'text/plain')">Create file</button>
_x000D_
_x000D_
_x000D_

And you would then download the file by putting the download attribute on the anchor tag.

The reason I like this better than creating a data url is that you don't have to make a big long url, you can just generate a temporary url.


Javascript has a FileSystem API. If you can deal with having the feature only work in Chrome, a good starting point would be: http://www.html5rocks.com/en/tutorials/file/filesystem/.


Choosing the location to save the file before creating it is not possible. But it is possible, at least in Chrome, to generate files using just JavaScript. Here is an old example of mine of creating a CSV file. The user will be prompted to download it. This, unfortunately, does not work well in other browsers, especially IE.

<!DOCTYPE html>
<html>
<head>
    <title>JS CSV</title>
</head>
<body>
    <button id="b">export to CSV</button>
    <script type="text/javascript">
        function exportToCsv() {
            var myCsv = "Col1,Col2,Col3\nval1,val2,val3";

            window.open('data:text/csv;charset=utf-8,' + escape(myCsv));
        }

        var button = document.getElementById('b');
        button.addEventListener('click', exportToCsv);
    </script>
</body>
</html>

_x000D_
_x000D_
setTimeout("create('Hello world!', 'myfile.txt', 'text/plain')");_x000D_
function create(text, name, type) {_x000D_
  var dlbtn = document.getElementById("dlbtn");_x000D_
  var file = new Blob([text], {type: type});_x000D_
  dlbtn.href = URL.createObjectURL(file);_x000D_
  dlbtn.download = name;_x000D_
}
_x000D_
<a href="javascript:void(0)" id="dlbtn"><button>click here to download your file</button></a>
_x000D_
_x000D_
_x000D_


function SaveBlobAs(blob, file_name) {
    if (typeof navigator.msSaveBlob == "function")
        return navigator.msSaveBlob(blob, file_name);

    var saver = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
    var blobURL = saver.href = URL.createObjectURL(blob), 
        body = document.body;

    saver.download = file_name;

    body.appendChild(saver);
    saver.dispatchEvent(new MouseEvent("click"));
    body.removeChild(saver);
    URL.revokeObjectURL(blobURL);
}

For latest browser, like Chrome, you can use the File API as in this tutorial:

window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.PERSISTENT, 5*1024*1024 /*5MB*/, saveFile, errorHandler);

_x000D_
_x000D_
function download(text, name, type) {_x000D_
  var a = document.getElementById("a");_x000D_
  var file = new Blob([text], {type: type});_x000D_
  a.href = URL.createObjectURL(file);_x000D_
  a.download = name;_x000D_
}
_x000D_
<a href="" id="a">click here to download your file</a>_x000D_
<button onclick="download('file text', 'myfilename.json', 'text/json')">Create file</button>
_x000D_
_x000D_
_x000D_

I think this can work with json files too if you change the mime type.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to file

Gradle - Move a folder from ABC to XYZ Difference between opening a file in binary vs text Angular: How to download a file from HttpClient? Python error message io.UnsupportedOperation: not readable java.io.FileNotFoundException: class path resource cannot be opened because it does not exist Writing JSON object to a JSON file with fs.writeFileSync How to read/write files in .Net Core? How to write to a CSV line by line? Writing a dictionary to a text file? What are the pros and cons of parquet format compared to other formats?

Examples related to dialog

Disable click outside of angular material dialog area to close the dialog (With Angular Version 4.0+) How to change DatePicker dialog color for Android 5.0 Android simple alert dialog Swift alert view with OK and Cancel: which button tapped? How to make a edittext box in a dialog How to check if activity is in foreground or in visible background? jquery ui Dialog: cannot call methods on dialog prior to initialization JavaScript: Create and save file Prevent Android activity dialog from closing on outside touch How to use OpenFileDialog to select a folder?

Examples related to save

What is the difference between --save and --save-dev? Basic http file downloading and saving to disk in python? Save byte array to file Saving Excel workbook to constant path with filename from two fields PHP - get base64 img string decode and save as jpg (resulting empty image ) How to edit/save a file through Ubuntu Terminal Write and read a list from file How to do a "Save As" in vba code, saving my current Excel workbook with datestamp? How to dump raw RTSP stream to file? Saving images in Python at a very high quality