DEV Community

Keff
Keff

Posted on • Updated on

Download Any File from Blob

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');
Enter fullscreen mode Exit fullscreen mode

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');

Enter fullscreen mode Exit fullscreen mode

Demo can be found here

Top comments (23)

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
Keff

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
Keff

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
Keff

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
 
nombrekeff profile image
Keff

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
Keff

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
Keff

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
 
boustanihani profile image
boustanihani • Edited

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
Keff

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 • Edited

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
Keff

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
 
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
Keff

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

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
Keff

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');
  });
Collapse
 
xiaotiandada profile image
_小田

developer.mozilla.org/zh-CN/docs/W...

maybe can add revokeObjectURL

Collapse
 
g7crservicenandankumarpandey profile image
Nandan

i need to download pdf from blob storage using url in the flutter

Collapse
 
st613mt profile image
st613mt

hello can i cange this code in order to save the file in local folder?
thank you for the explain

Collapse
 
nombrekeff profile image
Keff

I'm afraid you can't control where the file is stored, that's up to the user. This is for safety reasons