It's not clear from the question what you'll do with these dataURIs, but most of the time, you don't actually need it.
To be able to display a media from a user's File, or from a Blob, into your document, it is better to use the URL.createObjectURL()
method which will return a blobURI, that you can use like any url.
Non exhaustive list of blobURIs advantages :
- is synchronous. You don't need your Promise wrapping event handlers hell, all can be done in a single loop.
- is fast. The browser doesn't read the File or Blob passed, it just creates a symlink in the memory to the real File in the HDD.
- is memory light-weight. Because of previous point. When compared to
readAsDataURL()
, you should note that this latter will first read the file entirely, convert it to a base64 string (~34% bigger than original data), and finally, you will store this big string in the DOM's markup, making it always present in memory. From then, the browser will read it again, convert it to binary, read it again as binary and finally process it as an normal resource.
"But I need to send it to the server !"
Then send the File directly, as multipart data. Less work on the front-side, less work in the pipes (remember ~34%), and less work server-side if you wanted to save a File there.
Most server-side languages have easy built-ins methods to catch Files from POST requests, and you can send it easily from the front with the FormData
API.
Here is an example of your code, using blobURIs, which excpects all Files are images.
document.querySelector('input').onchange = function(){
// FileList doesn't have an forEach method yet
Array.prototype.forEach.call(this.files, function(file){
if(file.type.indexOf('image/' === 0)){
var i = new Image();
i.src = URL.createObjectURL(file); // creates a blobURI
document.body.appendChild(i);
}
});
};
<input type="file" multiple>
But note that this method can also have cons :
- Don't use it with MediaStreams. It will lock the source of the MediaStream until the blobURI is revoked (either when
URL.revokeObject(blobURI)
is called, or on an hard refresh of the page. In this case, you should use mediaElement.srcObject = MediaStream;
instead.
For Blobs you created, (not coming from an <input>
), the same point applies : the blob will be stuck in memory until expressly released. In this case, simply call URL.revokeObjectURL(blobURI)
once the resource is loaded.
img.onload = URL.revokeObjectURL(img.src);
img.src = URL.createObjectURL(the_Blob_I_built);