Gian T.
Gian T.

Reputation: 41

Angular Download Large blobs

I have an issue similar to this one where I am successfully downloading a blob generated from a backend via HTTP GET but the file is being saved to browser memory before the download begins.

There's no problem when downloading small files but it doesn't immediately download 100mb+ files.

Subscribing to the GET itself is causing the delay of saving the large files.

I'm using Angular 6 with an object store backend. Here's the download function:

finalDownload(url: string) {
  let headers = new HttpHeaders();

  headers = headers.append('X-Auth-Token', token);

  return this.http.get(url, { headers, responseType: 'blob' })
  .subscribe(response => {
    saveAs(response);
  })
}

Here's the process:

  1. User hits the download button
  2. GET request with headers is fired to back end
  3. As soon as I subscribe for the response, the blob is stored in browser memory.
  4. When the blob is completely stored in browser, the saveAs/download begins

Step 3 is where the issue is. This devtools screenshot with 108 MB transferred accumulates to the file size (I downloaded a 100 mb file) before the download itself to filesystem begins.

Upvotes: 4

Views: 3101

Answers (1)

junlan
junlan

Reputation: 261

You can try to use URL.createObjectURL:

URL.createObjectURL() can be used to construct and parse URLs. URL.createObjectURL() specifically, can be used to create a reference to a File or a Blob. As opposed to a base64-encoded data URL, it doesn’t contain the actual data of the object – instead it holds a reference.

The nice thing about this is that it’s really fast. Previously, we’ve had to instantiate a FileReader instance and read the whole file as a base64 data URL, which takes time and a lot of memory. With createObjectURL(), the result is available straight away, allowing us to do things like reading image data to a canvas.

Use the following code as reference

const blob = new Blob([data], { type: 'application/octet-stream' });
this.fileUrl = this.sanitizer.bypassSecurityTrustResourceUrl(window.URL.createObjectURL(blob));

Upvotes: 0

Related Questions