39

I'm trying to find a cross browser way to store data locally in HTML5. I have generated a chunk of data in a Blob (see MDN). Now I want to move this Blob to the actual filesystem and save it locally. I've found the following ways to achieve this;

  • Use the <a download> attribute. This works only in Chrome currently.
  • Microsoft introduces a saveAs function in IE 10 which will achieve this.
  • Open the Blob URL in the browser and save it that way.

None of these seems to work in Safari though. While (1) works in Chrome, (2) in IE and (3) in Firefox no one works in Safari 6. The download attribute is not yet implemented and when trying to open a blob using the URL Safari complains that URLs starting with blob: are not valid URLs.

There is a good script that encapsulates (1) and (3) called FileSaver.js but that does not work using the latest Safari version.

Is there a way to save Blobs locally in a cross browser fashion?

Erik
  • 663
  • 2
  • 7
  • 10
  • 1
    I am facing same issue in Safari. And used FileSaver.js for other browsers. I know the issue, you were facing long back. Just want to know, was it solved? – jrh Dec 08 '15 at 05:11

7 Answers7

22

FileSaver.js has beed updated recently and it works on IE10, Safari5+ etc.

See: https://github.com/eligrey/FileSaver.js/#supported-browsers

naugtur
  • 16,827
  • 5
  • 70
  • 113
  • Get the latest version and just use it. There's a bit of setting up involved like getting the content type right. I used FileSaver in one of my projects after trying to handle cross-browser issues myself. – naugtur Feb 13 '13 at 18:32
  • 7
    The [FileSaver.js demo](http://eligrey.com/demos/FileSaver.js/) is falling back to `data:` urls in Safari like my answer. example: data:text/plain;charset=UTF-8;base64,aGEgw6Agw6kgw7g= – forresto Feb 13 '13 at 18:37
  • Ok, that's right. It doesn't use the fileAPI too. So it got better since OP, but not good enough for you yet. You could contribute a bit of code that adds the functionality http://caniuse.com/fileapi – naugtur Feb 13 '13 at 18:48
7

The file name sucks, but this works for me in Safari 8:

        window.open('data:attachment/csv;charset=utf-8,' + encodeURI(csvString));

UPDATE: No longer working in Safari 9.x

malix
  • 3,566
  • 1
  • 31
  • 41
4

The only solution that I have come up with is making a data: url instead. For me this looks like:

window.open("data:image/svg+xml," + encodeURIComponent(currentSVGString));
forresto
  • 12,078
  • 7
  • 45
  • 64
  • This also worked for me in Safari 10.1: `window.open('data:application/json;charset=utf-8,' + encodeURIComponent('{"hello":"world"}'), '_blank')`. You can even cut-and-paste that into the browser console to see it open in a new tab. – Eric Dobbs Apr 18 '17 at 01:41
  • @EricDobbs Seems to be just doing a pop up and not downloading the file. Any ideas? – denislexic Nov 16 '18 at 22:38
  • @denislexic, it's not working for me anymore either. I'm sure Apple consider this a security fix. – Eric Dobbs Dec 17 '18 at 23:17
3

Here data is the array buffer data coming from response while making http rest call in js. This works in safari, however there might me some issue in filename as it comes to be untitled.

var binary = '';
var bytes = new Uint8Array(data);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
    binary += String.fromCharCode(bytes[i]);
}

var base64 = 'data:' + contentType + ';base64,' + window.btoa(binary);
var uri = encodeURI(base64);
var anchor = document.createElement('a');
document.body.appendChild(anchor);
anchor.href = uri;
anchor.download = fileName;
anchor.click();
document.body.removeChild(anchor);
Kirill
  • 2,590
  • 1
  • 17
  • 16
Apoorv
  • 51
  • 7
2

Have you read this article? http://updates.html5rocks.com/2012/06/Don-t-Build-Blobs-Construct-Them

Relating to http://caniuse.com/#search=blob, blobs are possible to use in safari.

You should consturct a servlet which delivers the blob via standard http:// url, so you can avoid using blob: url. Just make a request to that url and build your blob.

Afterwards you can save it in your filesystem or local storage.

tmthydvnprt
  • 10,398
  • 8
  • 52
  • 72
Sam
  • 2,707
  • 1
  • 23
  • 32
  • Creating the blob isn't the problem, but then you just can't open it with `window.open()` or download it. What do you mean by "consturct a servlet"? – forresto Feb 13 '13 at 18:18
  • 1
    He's talking about sending the contents to the server and making it respond with content-disposition:attachment etc. So you'd be downloading the file from the server after all, with a roundtrip. – naugtur Feb 13 '13 at 18:31
  • 6
    Well that defeats the purpose. – forresto Feb 13 '13 at 18:41
  • 1
    That's how it used to be done. It's not actually that bad for the server load, but it wastes bandwidth and makes user wait more. – naugtur Feb 13 '13 at 20:22
0

The download attribute is supported since ~safari 10.1, so currently this is the way to go.

David
  • 3,971
  • 1
  • 26
  • 65
0

This is the only thing that worked for me on safari.

   var newWindow = window.open();
   const blobPDF = await renderMapPDF(); // Your async stuff goes here
   if (!newWindow) throw new Error('Window could not be opened.');
   newWindow.location = URL.createObjectURL(blobPDF);
Marc
  • 1