w3c / FileAPI

File API
https://w3c.github.io/FileAPI/
Other
104 stars 44 forks source link

Consider adding `blob.dataUrl()` method, or some other analogue to `readAsDataURL` #179

Open josephrocca opened 2 years ago

josephrocca commented 2 years ago

Obviously data URLs and base64 in general should be avoided where possible, but unfortunately developers are often interacting with systems/libraries/APIs outside their control, and, practically, readAsDataURL is used a lot.

In fact, readAsDataURL is used about as much as readAsText and readAsArrayBuffer combined:

The blob.arrayBuffer() and blob.text() methods are delightful to use compared to previous methods, but for data URLs / base64 we're stuck with:

let file = ...;
let dataUrl = await new Promise((resolve, reject) => {
  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onload = () => resolve(reader.result);
  reader.onerror = (e) => reject(e);
});

which is the opposite of delightful. This is one of those cases where I'm "embarrassed" by how convoluted a simple task is in JS when helping someone who is new to JS.

There are a couple of proposals that are related to this issue:

That said, I really like promise-based blob.methodName() approach, and I'm hoping that we'll eventually get something like that for data URLs.

josephrocca commented 2 years ago

@annevk @domenic Wondering if either of you have any thoughts on this, or are aware of any prior discussion? Please feel free to ignore this ping (apologies in advance) if nothing comes to mind!

mkruisselbrink commented 2 years ago

I'd be very hesitant adding methods like that that don't also exists in the Body mixin. Of course Blob and Body already diverge in the methods they expose, but unless Body gets a method as well I'm not sure if there is a strong reason to add one to Blob.

josephrocca commented 2 years ago

Agreed, it would be great to add it to Body as well for consistency. That said, I don't think it'd be a good reason to hold this back if for some reason there were stakeholders that (for some reason) didn't want consistency here and were holding it back. So long as we don't go through any one-way doors that would prevent eventual consistency in the future, I think it's fine.

Going by those usage numbers readAsDataURL, devs want Blob.dataUrl a lot more than Blob.arrayBuffer/text, so if those existing methods are justified despite a current lack of consistency between Body and Blob, then I think Blob.dataUrl is more than justified.

annevk commented 2 years ago

What kind of use cases does this enable and are we sure those are best-served with data: URLs? data: URLs are not without issue, especially for larger payloads. They also don't work well with the kind of security UI browsers try to provide. I'd be rather hesitant to enshrine them further if (potentially novel) alternative solutions can perhaps provide for better UI and performance.

josephrocca commented 2 years ago

Yeah, it'd be great to see a breakdown of a small (but statistically significant) subset of those 1.6 million hits to see what percentage of them are using data URLs because they're roughly the best available option vs because the dev didn't know about better options like URL.createObjectURL (although the memory-leak potential of createObjectURL [due to forgetting to revoke] makes me instinctively avoid it if data is known to be small), or a different encoding, or whatever makes sense depending on what they're trying to do.

annevk commented 2 years ago

Yeah. And note that I don't think we should enshrine blob: URLs further either. They are similarly bad. Being able to assign objects to API endpoints is what's ultimately needed and what we should not have caved on at the start of all this.

josephrocca commented 2 years ago

Being able to assign objects to API endpoints is what's ultimately needed and what we should not have caved on

I'm out of the loop on this -- quick summary of this approach?

annevk commented 2 years ago

See HTMLMediaElement.prototype.srcObject for instance.

jimmywarting commented 1 year ago

Also related:

When ppl want to display a image preview from a file input, then i recommend ppl to just use URL.createObjectURL instead cuz data url use more memory than what a leaky data url dose that only have a reference point to the disc.

I do know the risk of not revoking things. https://stackoverflow.com/questions/49209756/do-i-always-need-to-call-url-revokeobjecturl-explicitly

dmurph commented 1 week ago

TPAC 2024: Feature request. Will revisit if .dataUrl() is added to body.