4

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.

Gian T.
  • 41
  • 4
  • What is the error (message)? – Lithilion Nov 13 '18 at 09:02
  • There's no error. It's just that the files get saved to browser memory first before the download itself starts. This gives the impression that the download isn't happening as the progress only appears in the network tab. I'll be editing the post to illustrate this. – Gian T. Nov 13 '18 at 09:06

1 Answers1

0

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));
junlan
  • 302
  • 1
  • 5