DEV Community

loading...

Download Any File from Blob

nombrekeff profile image Manolo Edge Updated on ・1 min read

I'm posting this here to have it accessible and maybe somebody will find it useful as well!

Deprecated (see next snippet)

function downloadBlob(blob, name = 'file.txt') {
    if (
      window.navigator && 
      window.navigator.msSaveOrOpenBlob
    ) return window.navigator.msSaveOrOpenBlob(blob);

    // For other browsers:
    // Create a link pointing to the ObjectURL containing the blob.
    const data = window.URL.createObjectURL(blob);

    const link = document.createElement('a');
    link.href = data;
    link.download = name;

    // this is necessary as link.click() does not work on the latest firefox
    link.dispatchEvent(
      new MouseEvent('click', { 
        bubbles: true, 
        cancelable: true, 
        view: window 
      })
    );

    setTimeout(() => {
      // For Firefox it is necessary to delay revoking the ObjectURL
      window.URL.revokeObjectURL(data);
      link.remove();
    }, 100);
}

// Usage
downloadBlob(blob, 'myfile.pdf');

NOTICE
As Kaltu pointed out in the comments: it seems "window.URL.createObjectURL()" had been blocked by all major browsers since 2019 for security reasons.

This approach should work as expected:

function downloadBlob(blob, name = 'file.txt') {
  // Convert your blob into a Blob URL (a special url that points to an object in the browser's memory)
  const blobUrl = URL.createObjectURL(blob);

  // Create a link element
  const link = document.createElement("a");

  // Set link's href to point to the Blob URL
  link.href = blobUrl;
  link.download = name;

  // Append link to the body
  document.body.appendChild(link);

  // Dispatch click event on the link
  // This is necessary as link.click() does not work on the latest firefox
  link.dispatchEvent(
    new MouseEvent('click', { 
      bubbles: true, 
      cancelable: true, 
      view: window 
    })
  );

  // Remove link from body
  document.body.removeChild(link);
}

// Usage
let jsonBlob = new Blob(['{"name": "test"}'])
downloadBlob(jsonBlob, 'myfile.json');

Demo can be found here

Discussion

pic
Editor guide
Collapse
kaltu profile image
Kaltu

I tried this snippet and hit by this error: "Uncaught TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided."
Upon a quick search it seems "window.URL.createObjectURL()" had been blocked by all major browsers since 2019 for security reasons.

Collapse
nombrekeff profile image
Manolo Edge Author

Ohh, damn, thanks for the information. I did not know this, it worked when I tested it, maybe my browser was not up to date or something.

I will add a warning and research a compatible way of doing it :P

Collapse
nombrekeff profile image
Manolo Edge Author

I've updated the post, the new snippet should work correctly.

If you find any issue in any browser, please let me know and I will be updating the snippet to adapt to any problems.

Collapse
gspteck profile image
GSPTeck

How would i use this to download a video which is a blob url?

Collapse
nombrekeff profile image
Manolo Edge Author

You could try this:

downloadBlob(completeBlob, 'myvideo.mp4');
Enter fullscreen mode Exit fullscreen mode

Instead of:

downloadBlob(URL.createObjectURL(completeBlob), 'myvideo.mp4');
Enter fullscreen mode Exit fullscreen mode

I think it does not like the data returned from createObjectURL, as it expects a blob that returns a DOMString.

Collapse
gspteck profile image
GSPTeck

It works, but the length of the video is always 0 seconds.
How would I fix this?

Thread Thread
nombrekeff profile image
Manolo Edge Author

I guess that has something to do with how you create the video blob. If you share your code I can take a look and check if there is something wrong

Thread Thread
Sloan, the sloth mascot
Comment deleted
nombrekeff profile image
Manolo Edge Author

Seems to be correct, as far as I can see.

can you see the video in any other way before converting to blob? Maybe in the page itself?

Thread Thread
gspteck profile image
GSPTeck

You can take a look at the full source code here: github.com/gspteck/RecScreen

Collapse
nombrekeff profile image
Manolo Edge Author

I think you can do it the same way, you just need to first convert the video into a blob, then you can pass it to the function as follows:

const videoBlob = createVideoBlob(video);
downloadBlob(videoBlob, 'myvideo.mp4');
Enter fullscreen mode Exit fullscreen mode
Collapse
geoliguay profile image
geoliguay

Hi, Is it also the same solution with blob images? im having the same problem which is broken image display in any browser. thanks.

Collapse
nombrekeff profile image
Manolo Edge Author

Hi, yup it should also work with images, just pass the binary data into the blob class constructor

Collapse
boustanihani profile image
boustanihani

Thanks for sharing.

Is there a way to get notified when the download actually starts and maybe also when the download is done?

Collapse
nombrekeff profile image
Manolo Edge Author

I don't think so, as it is a native download in another window/tab, like if you open a link to a file and chrome downloads it automatically.

I think you might be able to know when it is done, but have not played with that.

Collapse
applefacelisa profile image
Lisa

hi Manolo, thank you for sharing the code. I tried the new snippet on IE11 for downloading a PDF file but not work. Does it work for you? thanks.

Collapse
nombrekeff profile image
Manolo Edge Author

Hey, I have not tried on IE11, but I would guess it does not work as usual :P

I might look for an IE11 alternative and post it here as well, I will notify you if I do.

Collapse
felipepsantanna profile image
felipepsantanna

Hi, I'm trying to download a URL in Blob, would you know how to tell me how?

Collapse
nombrekeff profile image
Manolo Edge Author

Do you mean downloading a file from a URL?

If that is the case, you first need to read the URL as a blob. I think you can do this with FileReader or with a simple fetch/ajax/http request. Then, once you have the Blob you can use my method above to download it.

It would look something like this:

const url ='http://sample.example.file.doc'
const options = {};

fetch(url, options)
  .then( res => res.blob() )
  .then( blob => {
    downloadBlob(blob, 'filename.doc');
  });