Showing posts with label base64. Show all posts
Showing posts with label base64. Show all posts

Wednesday, February 21, 2018

ie11 Downloading Base64 documents

Leave a Comment

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/

3 Answers

Answers 1

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

Answers 2

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>

Answers 3

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;      }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

                    }                     else {                         var blobUrl = URL.createObjectURL(blob);                         window.open(blobUrl, "_blank");                     } 

//called method

Function pdfBlobConvesion(b64Data, contentType) {

    var 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 += 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; } 
Read More

Friday, April 1, 2016

Downloading a wav file using Horseman and PhantomJS losing data quality

Leave a Comment

I'm using PhantomJS and HorsemanJS to download a wav file from a remote server. However when the file is base64 encoded and written to a new file it loses quality which makes it unusable. The audio is there but its distorted which leads me to think that its an encoding problem. I'm running on Ubuntu 14.04 using node v5

Below is my script any ideas maybe to improve the base64 encoding?

var Horseman = require('node-horseman'); var horseman = new Horseman({cookiesFile:'./cookiejar'}); var fs = require('fs');  horseman.on("urlChanged", function(url){   console.log(url); });  horseman.on('consoleMessage', function( msg ){   console.log(msg); });  horseman   .userAgent("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36")   .open('https://remoteserver.com/audo.aspx?guid=01439900-5361-4828-ad0e-945b56e9fe51')   .waitForNextPage()   .type('input[name="password"]', process.env.PASS)   .type('input[name="username"]', process.env.UN)   .click("button:contains('Login')")   .waitForNextPage()   .evaluate(function(){     var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";      function base64encode(str) {         var out, i, len;         var c1, c2, c3;          len = str.length;         i = 0;         out = "";         while(i < len) {         c1 = str.charCodeAt(i++) & 0xff;         if(i == len)         {             out += base64EncodeChars.charAt(c1 >> 2);             out += base64EncodeChars.charAt((c1 & 0x3) << 4);             out += "==";             break;         }         c2 = str.charCodeAt(i++);         if(i == len)         {             out += base64EncodeChars.charAt(c1 >> 2);             out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));             out += base64EncodeChars.charAt((c2 & 0xF) << 2);             out += "=";             break;         }         c3 = str.charCodeAt(i++);         out += base64EncodeChars.charAt(c1 >> 2);         out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));         out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));         out += base64EncodeChars.charAt(c3 & 0x3F);         }         return out;     }      var url = $("a:contains('Uncompressed file')").attr("href");      console.log(url);      var out;     $.ajax({       'async' : false,       'url' : url,       'success' : function(data, status, xhr) {         console.log(status);         console.log(xhr.getResponseHeader('Content-Type'));         out = base64encode(data);       }     });     return out;   })   .then(function(out){     fs.writeFile('./mydownloadedfile.txt', out, 'base64', function(){       return horseman.close();     });   }); 

The content-type comes back as audio/wav

Any suggestions welcome!

1 Answers

Answers 1

Why don't you use Buffer for base64 encoding and decoding:

function base64Encode(plainData) {     return new Buffer(plainData).toString('base64'); }  function base64Decode(encodedData) {     return new Buffer(encodedData, 'base64').toString(); } 

in your script:

var out; $.ajax({   'async' : false,   'url' : url,   'success' : function(data, status, xhr) {     console.log(status);     console.log(xhr.getResponseHeader('Content-Type'));     out = base64Encode(data);   } }); return out; })... 
Read More

Thursday, March 31, 2016

Show BASE64 video with node/express

Leave a Comment

So, bit of an odd problem. I have a bunch of media files saved as base64 strings in mongo, some are images, some are videos.

I made an API for getting the media files:

app.get('/api/media/:media_id', function (req, res) {     media.findById(req.params.media_id)         .exec(function (err, media) {             if (err) {                 res.send(err);             }              var file = new Buffer(media.file, 'base64');             res.writeHead(200, {'Content-Type': media.type, 'Content-Transfer-Encoding': 'BASE64', 'Content-Length': file.length});             res.end(file);         }); }); 

Now, images have no problems. They load just fine, both directly from the API, and when I call the API from a front-end (for example <img src="/api/media/23498423">)

THE PROBLEM

If I fetch a video from a front-end, like the images - but with a video- or object-tag:

<video src="/api/media/3424525" controls></video> 

there's no problem, but if I load the video in a browser directly from the API:

http://localhost:8080/api/media/3424525 

the server process crashes, no errors. It simply just freezes up. And we're not talking about huge video files - it's a 1.5MB video.

The media type in the header for all the videos I'm testing with is video/mp4. Oh, and just to be clear: if I do the same with images, everything works perfectly.

EDIT:

Okay, so as suggested by @idbehold and @zeeshan I took a look at gridfs and gridfs-stream, and for the purpose of my app, this certainly is what I should have used in the first place. However, after implementing gridfs in my app, the problem still persists.

app.get('/api/media/:media_id', function (req, res) {     gfs.findOne({ _id: req.params.media_id }, function (err, file) {         if (err) {             return res.status(400).send(err);         }         if (!file) {             return res.status(404).send('');         }          res.set('Content-Type', file.contentType);         res.set('Content-Disposition', 'inline; filename="' + file.filename + '"');          var readstream = gfs.createReadStream({             _id: file._id         });          readstream.on("error", function (err) {             console.log("Got an error while processing stream: ", err.message);             res.end();         });          readstream.pipe(res);     }); }); 

When I call the media file (be it image or video) from a front-end, within a HTML tag, everything works out fine. But if I load a video (again, smallish videos from 1.5mb to max 6mb total size) directly in the browser, the server process freezes. To be a bit more clear: I am testing on windows, and the server app (server.js) is run in console. The console and the process it is running is what freezes. I cannot load any more pages/views in the node app, and I cannot even stop/kill/shutdown the node app or the console.

3 Answers

Answers 1

Streaming videos directly to/from GridFS using gridfs-stream either with mongodb-native db instance or mongoose.

var mongo = require('mongodb'),     Grid = require('gridfs-stream'),     db = new mongo.Db('yourDatabaseName', new mongo.Server("127.0.0.1", 27017)),     gfs = Grid(db, mongo);  //store app.post('/video', function (req, res) {     req.pipe(gfs.createWriteStream({         filename: 'file_name_here'     }));     res.send("Success!"); });  //get app.get('/video/:vid', function (req, res) {     gfs.createReadStream({         _id: req.params.vid // or provide filename: 'file_name_here'     }).pipe(res); }); 

for complete files and running project:

Clone node-cheat direct_upload_gridfs, run node app followed by npm install express mongodb gridfs-stream.

Answers 2

Truly an odd problem...
I could be way off, but it's worth a shot:

One of the differences when opening a url directly from the browser is that the browser will also try to fetch http://localhost:8080/favicon.ico (while trying to find the tab icon). Maybe the problem is not related to your video code, but rather to some other route, trying to handle the /favicon.ico request?

Have you tried using wget or curl?

Answers 3

I don't know the answer, maybe this is could be dumb suggest, but what is the browser are you using? Maybe something from Microsoft causes the problem...

Read More