Home > other >  How to convert reader.readAsDataURL(file) to readAsArrayBuffer
How to convert reader.readAsDataURL(file) to readAsArrayBuffer

Time:11-08

I have a component which allows me to drag multiple images onto the page and display the preview of those images. The following code achieves that:

displayPreviews(files: FileList) {

    for (let i = 0; i < files.length; i  ) {

      const file = files.item(i);

        const reader = new FileReader();

        reader.onload = () => {
          const image = reader.result as string;
          this.uploadFileArray.push({
            id: 'id',
            image: image,
          });
        };

        reader.readAsDataURL(file);

      }
    }

----------

<li *ngFor="let image of uploadFileArray">
    <div *ngIf="image && image !== ''" [ngStyle]="{'background-image': 'url('   image.image    ')'}"></div>
</li>

However, when selecting a large amount of images, it slows down the interaction with the rest of the page (form filling etc). I read that reader.readAsArrayBuffer can help alleviate that issue. However, I don't know how to integrate it. The below shows a grey box as it's no longer reading the image in the preview.

detectPhotos(files: FileList) {

    for (let i = 0; i < files.length; i  ) {
      // Reference to a file
      const file = files.item(i);

        const reader = new FileReader();

        reader.onload = () => {
          const image = reader.result;

          this.uploadFileArray.push({
            id: 'id',
            image: image,
          });
        };
        reader.readAsArrayBuffer(file);
      };
    
  }

CodePudding user response:

One issue of using readAsDataURL, the browser is going to have to convert blob to dataURI and then to display it, it's having to decode the dataURI. If you don't need to process the images first etc, you can use URL.createObjectURL to create a URL that references the BLOB instead.

Be aware, that URL.createObjectURL will keep the blob in memory until you call URL.revokeObjectURL(), it won't get GC'ed until you do. If using something like React, you could attach this to a useEffect dismount, if using pure JS you will want to keep a reference of these to clear when your done.

document.querySelector('input').addEventListener('change', function (e) {
  for (const file of e.target.files) {
    const url = URL.createObjectURL(file);
    const img = document.createElement('img');
    img.style.width = "100px";
    img.setAttribute('src', url);
    img.onload = () => {
      URL.revokeObjectURL(url);     
    };
    document.querySelector('#images').appendChild(img);
  }
});
<input type="file" name="files" multiple accept="image/*"/>
<div id="images"></div>

  • Related