4

As I've been looking for a way to create and download a text file from a website with JavaScript, I've found a bunch of solutions but generally using either Blob/createObjectURL or otherwise encodeURIComponent, with the former being more popular from what I've seen. Below I show two examples: note that only one-two lines in the beginning are different in the two functions (which I noted in comments).

Blob/createObjectURL:

function dl_as_file_Blob(filename_to_dl, data_to_dl) {
    let blobx = new Blob([data_to_dl], { type: 'text/plain' }); // ! Blob
    let elemx = window.document.createElement('a');
    elemx.href = window.URL.createObjectURL(blobx); // ! createObjectURL
    elemx.download = filename_to_dl;
    elemx.style.display = 'none';
    document.body.appendChild(elemx);
    elemx.click();
    document.body.removeChild(elemx);
}

encodeURIComponent:

function dl_as_file_URI(filename_to_dl, data_to_dl) {
    let elemx = document.createElement('a');
    elemx.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(data_to_dl); // ! encodeURIComponent
    elemx.download = filename_to_dl;
    elemx.style.display = 'none';
    document.body.appendChild(elemx);
    elemx.click();
    document.body.removeChild(elemx);
}

What I'd like to know is whether there is any reason to prefer one over the other. So far I could find two small differences. First, encodeURIComponent is more widely supported by browsers than createObjectURL. Second, Blob seems not to support encoding. Based on this, I'd choose the encodeURIComponent solution, but I wonder if there is a reason for why I see the Blob/createObjectURL solution more often.

EDIT: The question above is quite general, so let me narrow down a bit for my specific use case: I want to allow users to download a simple (utf-8), relatively small (max 100-200 kB) text (the results of a completed self-assessment test). There is no really sensitive data involved, and the file is only needed for this purpose alone, on the client-side. Nonetheless, I also welcome more general answers, since I'm curious about the differences.

gaspar
  • 898
  • 1
  • 13
  • 26

1 Answers1

3

I wonder if there is a reason for why I see the Blob/createObjectURL solution more often.

IMHO there are a few possible reasons:

TL;DR

  1. Performance

  2. Security

  3. API access

  4. It is an object

  5. It looks cooler


1. Performance

  • You have full control of the content.

  • You can store and access very large amount of data: very fast (async, worker threads) to/from the Web, the local filesystem, local databases, and also other windows and workers.

  • You can store Objects in a performant way.

  • Content can be accessed as text, as typed arrays, or as URLs.

  • You can splitt stored data: for better performance results (gains are like static lenght arrays vs dynamic ones).

  • Blobs you can store in memory or on disks.

  • Blobs can be read from and written to/from the Web, the local.

  • Garbage collection.

Most importantly, client-side JavaScript File object is a subtype of Blob, a File is just a Blob of data: with a name and a modification date. You can obtain File objects from <input type="file"> elements and from the drag-and-drop API.

2. Security

  • You have full control of the content. (at least for now)

  • CORS: Blob is same origin, while data: has to be specified in the cors rules, btw data: can be used to be/do evil things.

  • You can do even much more evil things with data:, but this should not be posted/discussed here.

3. API access

Once you have a Blob, there are various things you can do with it, many of them symmetrical to the items above:

  • You can send a Blob to another window or worker thread with postMessage().

  • You can store a Blob in a client-side database.

  • You can upload a Blob to a server by passing it to the send() method of an XMLHttpRequest object. (remember, a File object is just a specialized kind of Blob).

  • You can use the createObjectURL() function to obtain a special blob:// URL that refers to the content of a `Blob, and then use this URL with the DOM or with CSS.

  • You can use a FileReader object to asynchronously (or synchronously, in a worker thread) extract the content of a Blob into a string or ArrayBuffer.

  • You can use the Filesystem API and the FileWriter object to write a Blob into a local file.

4. It is an object

  • I think, i don't need to enter this discussion :D

5. It looks cooler

  • A short Blob URL looks much better than for example a 4096 kB string.

  • You can do much more cool stuff with Blob.

sources:

Community
  • 1
  • 1
Stefano
  • 224
  • 4
  • 7
  • 1
    Thanks for your answer! It's quite illuminating, so I already accepted it for now, though I realize my question was a bit too general for what I actually had in mind, see my edit. In this respect, while you list some good points about `Blob`, I see no serious arguments **against** using `encodeURIComponent` for such simple use cases as mine (again see the edit). – gaspar May 12 '20 at 07:45
  • 1
    More in general, some of your points are not that clear to me. In particular, you say twice "You have full control of the content." But what exactly do you mean by that? Can you perhaps give an example of `Blob` vs. `encodeURIComponent` where the former is more flexible? Another thing is "You can do much more cool stuff with Blob." Again, what exactly? – gaspar May 12 '20 at 07:46
  • here an very nice answer: [link](https://stackoverflow.com/a/32295448/3626361) (Performance URI is limited, Control: you decide for example what type of mime:data you want to download/specify, URI would let you do the explamne with ocetstream only.) – Stefano Jun 30 '20 at 19:59
  • about the cool stuff, there is some uncool stuff too, but posting here PoC's would land me a ban. i can just talk about the tip of the iceberg. for example you can manipulate a file, you serve it as a image[jpg,png,svg], but generaly its a malicious application or script. you can then get it by "drive by download" etc. – Stefano Jun 30 '20 at 20:08
  • the cool stuff, blobbed data is easier to direcly access.but in nearly every example, there a main reasons to prefer blob over URI, basicaly its always performance. if you work with larger data or want a very fast app/script, you always should imho the blob variant. when i find some time, i will update my post with more examples. – Stefano Jun 30 '20 at 20:09