Skip to content Skip to sidebar Skip to footer

How To Make The Following Readasdataurl Return Multiple Readasdataurls?

This function read files gotten from an input field and return their dataUrls: readAsDataURL (target) { // target => var reader = new Fil

Solution 1:

Have you tried using Promise.all? You might be able to do something like:

fileToDataURL(file) {
  var reader = newFileReader()
  returnnewPromise(function (resolve, reject) {
    reader.onload = function (event) {
      resolve(event.target.result)
    }
    reader.readAsDataURL(file)
  })
}  

readAsDataURL (target) {
  // target => <input type="file" id="file">var filesArray = Array.prototype.slice.call(target.files)      
  returnPromise.all(filesArray.map(fileToDataURL))
}

This essentially does the same thing you had setup, but creates a promise for each one, returning the result in an array only once all have been completed.


I forgot that you cannot treat target.files directly as an array, so it needs to be converted first. For this you can use: Array.prototype.slice.call(target.files)

Solution 2:

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 yetArray.prototype.forEach.call(this.files, function(file){
    if(file.type.indexOf('image/' === 0)){
      var i = newImage();
      i.src = URL.createObjectURL(file);  // creates a blobURIdocument.body.appendChild(i);
      }
    });
  };
<inputtype="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);

Post a Comment for "How To Make The Following Readasdataurl Return Multiple Readasdataurls?"