12

I have tried pretty much everything at this point and I cannot get anything to work in ie.

I need ie to download base64 documents from an attachment panel. I have no access to the server side code or database. The images cannot be stored in a folder to be pulled up, they need to be presented this way.

I have tried using a plain link and sticking the base64 sting in there and it just opens up a new blank window.

<a target="_blank" download class="btn btn-primary downloadAttachment" href="' + blobUrl + '" >Download</a>

I have tried turning the url into a blob and opening the blob and that resulted in the browser not doing anything.

function base64toBlob(base64Data, contentType) {
    contentType = contentType || '';
    var sliceSize = 1024;
    var byteCharacters = base64Data;
    var bytesLength = byteCharacters.length;
    var slicesCount = Math.ceil(bytesLength / sliceSize);
    var byteArrays = new Array(slicesCount);

    for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
        var begin = sliceIndex * sliceSize;
        var end = Math.min(begin + sliceSize, bytesLength);

        var bytes = new Array(end - begin);
        for (var offset = begin, i = 0 ; offset < end; ++i, ++offset) {
            bytes[i] = byteCharacters[offset].charCodeAt(0);
        }
        byteArrays[sliceIndex] = new Uint8Array(bytes);
    }
    return new Blob(byteArrays, { type: contentType });
}

I am completely and totally stuck. I have tried everything from google and on here.

My two latest attempts here

https://jsfiddle.net/pqhdce2L/

http://jsfiddle.net/VB59f/464/

zazvorniki
  • 3,512
  • 21
  • 74
  • 122
  • Have you tried https://stackoverflow.com/questions/37203771/download-base64-data-using-javascript-ie11? – JDB Feb 14 '18 at 20:55
  • 1
    @JDB It would appear so, as that is the exact same code as in this question, except for an `atob()` call that is missing here. – Michael Geary Feb 14 '18 at 20:57
  • 1
    @JDB, Yes as Michael said this is the same code...but my string is being decoded backend so I did not use the atob() – zazvorniki Feb 14 '18 at 21:02
  • Ok... but the accepted answer on that question uses `msSaveBlob` which I don't see in your question. – JDB Feb 14 '18 at 21:03
  • Or did you not include all relevant code in your question? If so, please see the FAQ: [Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it **in the question itself**.](https://stackoverflow.com/help/on-topic) – JDB Feb 14 '18 at 21:04
  • @JDB, there is no accepted answer on that question. And yes I have included all my code within the jsFiddles and on the screen – zazvorniki Feb 14 '18 at 21:06
  • Sorry... the highest upvoted answer. While links to jsfiddle are acceptable, please note that you should include all relevant code in the question body. The code in your question does not include any reference to msSaveBlob, so it's not surprising that multiple users now (myself included) have turned to that first. See https://meta.stackoverflow.com/a/254430/211627 – JDB Feb 14 '18 at 21:09
  • 1
    @JDB, I am not just pasting links to my website. I have provided code within the question and have provided examples of what I have tried. To paste all that code within the question seemed overkill and not helpful. – zazvorniki Feb 14 '18 at 21:16
  • No... this part: "*As some people are more used to them, consider additionally providing it on JS Bin and/or jsFiddle. Since these are third party services and may be unavailable at any time, **make sure your question can be understood without visiting these websites**.*" – JDB Feb 14 '18 at 21:17
  • @JDB, to answer the question if I had tried that answer is yes, I could not get it to work in ie in a Fiddle so I have not tried it in my actual code – zazvorniki Feb 14 '18 at 21:17
  • 1
    @JDB, My question can be understood. I had two developers read it before I submitted it. Please can we stop debating this and focus on a solution to this issue? – zazvorniki Feb 14 '18 at 21:18
  • I'm not trying to debate you... I posted a link to a question that directly answers your question. You are saying that you already tried it, but there's no evidence of that in your question. If you have already tried that, please update your question to provide that additional information. Specifically, when you tried `msSaveBlob`, what was the result? – JDB Feb 14 '18 at 21:20

4 Answers4

4

Some time ago I've coined this function to make ("offer/initialize") a download of an xlsx or csv content accepting both a Blob or a base64 string:

// Initializes a file download of a provided content
//
// Not usable outside browser (depends on window & document)
//
// @param {Blob|base64} cont File content as blob or base64 string
// @param {string} ftype File type (extension)
// @param {string} [fname='export.' + ftype] File name
// @param {string} [mime='application/zip'] File mime type
// @returns {void}
function makeFileDownload(cont, ftype, fname, mime) {
    if (!fname) fname = 'export.' + ftype;
    if (!mime) mime = ftype === 'csv' ? 'text/csv' : 'application/zip'; // or 'application/vnd.ms-excel'

    if (Object.prototype.toString.call(cont) === '[object Blob]'
            && window.navigator && window.navigator.msSaveBlob) {
        window.navigator.msSaveBlob(cont, fname);
    }
    else {
        var downloadLink = document.createElement('a');
        downloadLink.download = fname;
        downloadLink.href = typeof cont === 'string'
            ? 'data:' + mime + ';base64,' + cont
            : window.URL.createObjectURL(cont);
        downloadLink.onclick = function(e) { document.body.removeChild(e.target); };
        downloadLink.style.display = 'none';
        document.body.appendChild(downloadLink);
        downloadLink.click();
    }
};

This should be able to accept both Blob and base64 string - you should get the idea how it's being done for either a Blob and a base64 string from the if/else block.

If passing it base64 string is problematic just convert it to a Blob first (as suggested for example in this SO question, this answer is specifically aimed at IE11). Adjust the mime defaults according to your expected usage.

I suppose you already have the content (Blob/base64), keep your original link (which I suppose is to be clicked by an user) a plain link or rather a button (i.e. without the download/href attributes), attach it a click event handler where you'll call the function and it should initialize the download for you:

document.querySelector('#originalLink').addEventListener('click', function () {
    makeFileDownload(content, extension, filename, mimetype);
});
Tomas Varga
  • 1,432
  • 15
  • 23
  • IE11 allows `querySelector()`? – Patrick Roberts Feb 14 '18 at 21:31
  • If unsure, I'd say the best source on checking compatibility issues is [MDN](https://developer.mozilla.org/en-US/docs/Web/API); see [document.querySelector()](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) - there's always a compatibility table at the end of the page (even with additional notes on exceptions, partial implementations etc.) – Tomas Varga Feb 14 '18 at 21:33
  • So this code downloads the file immediately on page load? Because that's what it seems to do when I tried to implement it. http://jsfiddle.net/VB59f/477/ – zazvorniki Feb 14 '18 at 21:56
  • Not on a page load but on the function call - the "self-clicked" link is created and clicked when you call the function (which of course you can do at the page load). – Tomas Varga Feb 14 '18 at 21:59
  • @TomasVarga, I do not have an original link. I was creating that with the download attached to it. But when I created one for demo purposes, the on click will not work without the href. I added a blank href and the download fails each time in Chrome so I'm assuming that will not work in ie either. http://jsfiddle.net/VB59f/489/ – zazvorniki Feb 15 '18 at 21:34
  • I also tried the solution in the link above (before I opened this question) and in ie I get the error access denied. https://jsfiddle.net/f9vo1mmn/9/ – zazvorniki Feb 15 '18 at 21:53
2

If you are trying to generate blob URL in IE, it will not work.

We have to download the file to local by using below code:

function printPdf(id) {
  $.ajax({
    url: 'url',
    type: 'POST',
    data: { 'ID': id },
    success: function (result) {

      var blob = pdfBlobConvesion(result.PdfUrl, 'application/pdf');
      var isIE = /*@cc_on!@*/false || !!document.documentMode;
      // Edge 20+
      var isEdge = !isIE && !!window.StyleMedia;
      if (isIE || isEdge) {
        window.navigator.msSaveOrOpenBlob(blob, "ProviderOfficePDF.pdf");
      }
      else {
        var blobUrl = URL.createObjectURL(blob);
        window.open(blobUrl, "_blank");
      }
    }
  });
}

function pdfBlobConvesion(b64Data, contentType) {
  contentType = contentType || '';
  var sliceSize = 512;
  b64Data = b64Data.replace(/^[^,]+,/, '');
  b64Data = b64Data.replace(/\s/g, '');
  var byteCharacters = window.atob(b64Data);
  var byteArrays = [];

  for ( var offset = 0; offset < byteCharacters.length; offset = offset + sliceSize ) {
    var slice = byteCharacters.slice(offset, offset + sliceSize);

    var byteNumbers = new Array(slice.length);
    for (var i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    var byteArray = new Uint8Array(byteNumbers);

    byteArrays.push(byteArray);
  }

  var blob = new Blob(byteArrays, { type: contentType });
  return blob;
}
KyleMit
  • 30,350
  • 66
  • 462
  • 664
0

IE, in classic fashion, requires you to use a proprietary method for "saving" a blob.

msSaveBlob or msSaveOrOpenBlob is what you're looking for.

Instead of adding it as the href, add an onclick handler to your a tag and call navigator.msSaveBlob(blob, "Sample Name");

Additionally if you need to support other browsers you'll need some other code to support those browsers.

For example:

var content = new Blob(["Hello world!"], { type: 'text/plain' });
var btn = document.getElementById('btn');

if (navigator.msSaveBlob) {
  btn.onclick = download;
} else {
  btn.href = URL.createObjectURL(content);
  btn.download = true;
}

function download() {
  if (navigator.msSaveBlob) {
    navigator.msSaveBlob(content, "sample.txt");
  }
}
<a id="btn" href="#">Download the text!</a>
Hargo
  • 1,256
  • 1
  • 16
  • 24
  • I have tried adding a click to the a tag, but ie throws an error saying that the method is not supported. How would I implement the msSaveBlob? I have never used this or done any of these methods so I'm a noob here. haha – zazvorniki Feb 14 '18 at 21:04
  • @zazvorniki, I've added an example to hopefully help. – Hargo Feb 14 '18 at 21:21
  • Thank you! However, I tried to plug in a Base64 image to see how that would behave since I am dealing with all sorts of different files and I don't think I'm doing it correctly? https://jsfiddle.net/pqhdce2L/111/ – zazvorniki Feb 14 '18 at 21:46
  • @zazvorniki You're using the `Blob` constructor incorrectly. It expects binary data, not base64 encoded data. (You're also missing a closing quote I believe). If you have base64 you'll need to convert the base64 to a typed array and pass _that_ to the blob constructor. See https://stackoverflow.com/a/41106346/4313043 for one way to create a typed array with your data). – Hargo Feb 14 '18 at 21:59
  • Like I said I have never used a blob constructor before. This question was about base64 documents. How would I go about using that in this instance? I have been trying to convert it into arrays with no success. – zazvorniki Feb 14 '18 at 22:22
  • @zazvorniki: This answer is working as its supposed to. You have to just pass the decoded Uint8Array to the blob. A sample is here https://jsfiddle.net/karthick6891/rztrngd2/1/. Its the same code as Hargobind and very very simillar to what JDB has said. – karthick Feb 20 '18 at 21:00
0
var data = item;
var fileName = name;
if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE 
workaround
var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], {type: 'application/octet-stream'});
window.navigator.msSaveOrOpenBlob(blob, fileName);
}
else if( agent.indexOf('firefox') > -1)
{
console.log(extention,'item111')
var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
  byteNumbers[i] = byteCharacters.charCodeAt(i);
 }
 var byteArray = new Uint8Array(byteNumbers);
//var FileSaver = require('file-saver');
 var blob = new Blob([byteArray], {type: "application/octet-stream"});
 saveAs(blob, fileName);
  }
 else{
  this.fileDownload='data:application/octet-stream;base64,'+item;
   var link = document.createElement("a");
   const fileName=name;
   link.href = this.fileDownload;
   link.download=fileName;
   link.click();
  }
  }