50

I have this in my Angular.js controller that downloads a CSV file:

 var blob = new Blob([csvContent.join('')], { type: 'text/csv;charset=utf-8'});
 var link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
 link.href = URL.createObjectURL(blob);
 link.download = 'teams.csv';
 link.click();

This works perfectly in Chrome but not in IE. A browser console log says:

HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed.

What does it mean and how can I fix it?

Mike
  • 14,010
  • 29
  • 101
  • 161
raberana
  • 11,739
  • 18
  • 69
  • 95

11 Answers11

83

Try this using, this or useragent

if (navigator.appVersion.toString().indexOf('.NET') > 0)
        window.navigator.msSaveBlob(blob, filename);
else
{
 var blob = new Blob(['stringhere'], { type: 'text/csv;charset=utf-8' });
 var link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
 link.href = URL.createObjectURL(blob);
 link.download = 'teams.csv';
 link.click();
}
sameh.q
  • 1,691
  • 2
  • 23
  • 48
Naim Sulejmani
  • 1,130
  • 9
  • 10
  • 13
    +1. But to make it work in Firefox I had to add : `document.body.appendChild(link);` before the `click()` - and then remove the link again ! – Pierre Henry Aug 22 '16 at 12:53
  • 1
    @PierreHenry or you make the link invisible by `link.setAttribute('style','display:none');` – Alexander Behling Mar 28 '19 at 09:35
  • 5
    It's not recommend to rely on navigator.appVersion (@see https://developer.mozilla.org/en-US/docs/Web/API/NavigatorID/appVersion) I would recommend to modify the if-statement to this: `if (typeof(window.navigator.msSaveBlob) == 'function'){....` – Alexander Behling Mar 28 '19 at 09:44
55

IE won't allow you to open blobs directly. You have to use msSaveOrOpenBlob. There's also msSaveBlob

if (window.navigator && window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
    var objectUrl = URL.createObjectURL(blob);
    window.open(objectUrl);
}
Vinícius Todesco
  • 1,907
  • 13
  • 14
21

I needed to use a Blob to download a converted a base64 PNG image. I was able to successfully download the blob on IE11 with window.navigator.msSaveBlob

See the following msdn link: http://msdn.microsoft.com/en-us/library/hh779016(v=vs.85).aspx

Specifically, you should call:

window.navigator.msSaveBlob(blobObject, 'msSaveBlob_testFile.txt');

where blobObject is a Blob created in the usual fashion.

alex
  • 756
  • 4
  • 12
11

Complete Solution for Chrome, Internet Explorer Firefox and Opera

There are lots of nice bits on this page, but I had to use a combination of a few things to get it all to work. Hopefully this helps you.

  1. Use a button or link to trigger a function called download():
<button class="button-no save-btn" ng-click="download()">DOWNLOAD</button>
  1. Put this in your controller:
$scope.download = function () {

    // example shows a JSON file
    var content = JSON.stringify($scope.stuffToPutInFile, null, "  ");
    var blob = new Blob([content], {type: 'application/json;charset=utf-8'});

    if (window.navigator && window.navigator.msSaveBlob) {

        // Internet Explorer workaround
        $log.warn("Triggering download using msSaveBlob");
        window.navigator.msSaveBlob(blob, "export.json");

    } else {
        
        // other browsers
        $log.warn("Triggering download using webkit");
        var url = (window.URL || window.webkitURL).createObjectURL(blob);
        
        // create invisible element
        var downloadLink = angular.element('<a></a>');
        downloadLink.attr('href', url);
        downloadLink.attr('download', 'export.json');
        
        // make link invisible and add to the DOM (Firefox)
        downloadLink.attr('style','display:none');
        angular.element(document.body).append(downloadLink);
        
        // trigger click
        downloadLink[0].click();
    }
};
reformed
  • 4,505
  • 11
  • 62
  • 88
slugmandrew
  • 1,776
  • 2
  • 25
  • 45
1

What's your IE browser version? You need a modern browser or IE10+ http://caniuse.com/bloburls

user1322092
  • 4,020
  • 7
  • 35
  • 52
1

Maybe you need some delay. What about with:

link.click();
setTimeout(function(){
    document.body.createElementNS('http://www.w3.org/1999/xhtml', 'a');
    URL.revokeObjectURL(link.href);  
}, 100);
pmiranda
  • 7,602
  • 14
  • 72
  • 155
1

I needed to get the download feature to work in Chrome and IE11. I had good success with this code.

HTML

<div ng-repeat="attachment in attachments">
  <a ng-click="openAttachment(attachment)" ng-href="{{attachment.fileRef}}">{{attachment.filename}}</a>
</div>

JS

$scope.openAttachment = function (attachment) {
  if (window.navigator && window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(
      b64toBlob(attachment.attachment, attachment.mimeType),
      attachment.filename
    );
  }
};
Andrii Muzalevskyi
  • 3,261
  • 16
  • 20
Json
  • 11
  • 2
1

Done it this way, working fine for me.

downloadFile(data) {
    if (navigator.msSaveBlob) {
      let blob = new Blob([data], {
        "type": "text/csv;charset=utf8;"
      });
      navigator.msSaveBlob(blob, this.fileName);
    }
    else {
      let blob = new Blob(['\ufeff' + data], { type: 'text/csv;charset=utf-8;' });
      let $link = document.createElement("a");
      let url = URL.createObjectURL(blob);
      $link.setAttribute("target", "_blank");
      $link.setAttribute("href", url);
      $link.setAttribute("download", this.fileName);
      $link.style.visibility = "hidden";
      document.body.appendChild($link);
      $link.click();
      document.body.removeChild($link);
    }
  }
Dharam Mali
  • 907
  • 1
  • 11
  • 24
0

Try to use this instead : var blob = file.slice(0, file.size);

user1942990
  • 60
  • 1
  • 6
  • See this Question / answser: http://stackoverflow.com/questions/14206127/createobjecturl-does-not-work-in-ie10 – vanthome Jan 30 '14 at 16:55
0

Create polyfill method as below,had a variable filename since in my case download filename was static.This method will be called while blob function is not supported as in case of Internet explorer

    if (!HTMLCanvasElement.prototype.toBlob) {
            Object.defineProperty(HTMLCanvasElement.prototype, 
            'toBlob', {
                value: function (callback, type, quality) {
                var canvas = this;
                setTimeout(function () {
                var binStr = atob(canvas.toDataURL(type, quality).split(',')[1]),
                    len = binStr.length,
                    arr = new Uint8Array(len);

                for (var i = 0; i < len; i++) {
                    arr[i] = binStr.charCodeAt(i);
                }
                var blob = new Blob([arr], {
                    type: 'image/png'
                });
                window.navigator.msSaveOrOpenBlob(blob, fileName);
            });
        }
    });
}
0
try {
      const blob = new Blob([res.body], {
        type: res.headers.get('Content-Type'),
      });
      const file = new File([blob], this.getFileName(res), {
        type: res.headers.get('Content-Type'),
      });

      saveAs(file);
    } catch (err) {
      var textFileAsBlob = new Blob([res.body], {
        type: res.headers.get('Content-Type'),
      });
      window.navigator.msSaveBlob(textFileAsBlob, this.getFileName(res));
    }

To get the file name. Use the below function.

getFileName(response: any) {
    let name: string;
    try {
      const contentDisposition: string = response.headers.get(
        'content-disposition'
      );
      const [, filename] = contentDisposition.split('filename=');
      name = filename;
    } catch (e) {
      name = 'File_Name_Not_Specified_' + new Date();
    }
    return name;
  }

This worked for me.

Monish N
  • 330
  • 1
  • 6
  • 15
  • new File() constructor is not working on iE11. is there any alternative solution for this ? to convert a blob file to File() type without using File constructor on IE11. – Vamsi Jul 22 '21 at 03:13
  • Refer this https://stackoverflow.com/a/39329659/8437877. Also check for other browser compatibility using this https://caniuse.com/?search=file. – Monish N Jul 23 '21 at 10:30
  • It was mentioned there to download or save file to local but what I need is to send that file to API request in File type format. just wondering is that actually possible on IE11 ? – Vamsi Jul 23 '21 at 11:00