Get URL from Blob in Internet Explorer using JavaScript - javascript

I need to print a PDF file which I obtain through a GET request in JavaScript. In order to do the actual printing I use PrintJS, which can be used to print from a specific PDF URL.
My code looks something like this:
printChart() {
var req = new XMLHttpRequest();
req.open('GET', 'http://localhost:8080/test.pdf', true);
req.responseType = 'blob';
req.onload = function (event) {
var blob = req.response;
var blobURL = window.URL.createObjectURL(blob);
printJS(blobURL);
};
req.send();
}
This works fine in Chrome, but the problem is it does not print anything in Internet Explorer (tested in IE 11). Apparently, window.URL.createObjectURL does not work properly in IE.
Although there is a msSaveOrOpenBlob method in IE but this doesn't help me very much, since I need to print the PDF, not to save it.

Related

Angular download PDF on IOS mostly opens in same tab

I'm using file-saver in my angular application to download a PDF generated in my backend. The library generally works fine on desktop and android. But I don't seem to be able to download a file on IOS. file-saver doesn't, as stated in on the GitHub page, open the blob in a new Page either. it jus opens on the same page (not wanted). Funnily enough it works fine in safari (it opens a dialog that asks me to download and then downloads it without opening it). In any other browser (opera, firefox and chrome) it doesn't seem to work.
I've tried file-saver, downloadJ, creating an anchor tag myself together with the download attribute, using the application/octet-stream mime-type and several other solutions posted on the internet. All of these methods in most browsers just doe nothing or open the PDF blob in the same page instead of downloading it or opening it in a new tab (as file-saver states it would do on IOS).
I'm generating the PDF in a Google Cloud Function. Is there maybe a way to skip the whole client side of things and make the browser download the file directly from there?
Does anyone have another idea on how to download PDF's on mobile IOS (e.g. with a service worker or something)?
Thanks in advance
Best solution as per new chrome specification https://developers.google.com/web/updates/2018/02/chrome-65-deprecations
Vanilla JavaScript
public static downloadFile(url: string): void {
const xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = () => {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
const blobUrl = window.URL.createObjectURL(xmlHttp.response);
const e = document.createElement('a');
e.href = blobUrl;
e.download = blobUrl.substr(blobUrl.lastIndexOf('/') + 1);
document.body.appendChild(e);
e.click();
document.body.removeChild(e);
}
};
xmlHttp.responseType = 'blob';
xmlHttp.open('GET', url, true);
xmlHttp.send(null);
}
If you're using angular try this.
async downloadBrochure(url: string) {
try {
const res = await this.httpClient.get(url, { responseType: 'blob' }).toPromise();
this.downloadFile(res);
} catch (e) {
console.log(e.body.message);
}
}
downloadFile(data) {
const url = window.URL.createObjectURL(data);
const e = document.createElement('a');
e.href = url;
e.download = url.substr(url.lastIndexOf('/') + 1);
document.body.appendChild(e);
e.click();
document.body.removeChild(e);
}

Safari 9 XMLHttpRequest Blob file download

Hello JavaScript gurus,
I need a file download functionality using XMLHttpRequest (with responseType="blob") that works in Safari 9+.
At the moment I'm using FileSaver.js like this:
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// using FileSaver.js to save blob
saveAs(xhr.response, filename);
// notify download finished, resolve promise
defer.resolve(true);
}
};
xhr.send();
which works fine in all main browsers but not in current version (9.x) of Safari.
I'll get a "Failed to load resource: Frame load interrupted". Usually a download is a zip file but I also tried to set "application/octet-stream".
I have one requirement: I need to know when then download has finished on client-side so using an iframe is no option (I guess).
I'm thankful for any hint how to download a file in Safari using XHR (no Flash).
Thanks,
Chris
Simple answer:
There is no solution!
See also: https://forums.developer.apple.com/message/119222
Thanks Safari ... my new almost IE6

Fetching BLOB in Chrome Android

I'm struggling to fetch an HTML5 video using xhr2 and blob responseType with Chrome on Android 4.2. The code works perfectly on Chrome and Firefox desktop and on Firefox Android 4.2 (with FF desktop, I use a webm video instead of the mp4).
// Taking care of prefix
window.URL = window.URL || window.webkitURL;
// This function download the video
var loadVideo = function() {
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', addVideoFile, false);
xhr.open('GET', "videos/myvideo.mp4" , true);
xhr.responseType = 'blob';
xhr.send();
};
// this function sets the video source
var addVideoFile = function() {
if(4 == this.readyState && 200 == this.status) {
var video = document.getElementById('vid'),
blob = this.response;
video.src = window.URL.createObjectURL(blob);
console.log('video ready');
}
};
loadVideo();
Can anyone explain me why this does not work with Chrome on Android? If I plug my phone to use the remote debugging, the console will display 'video ready', suggesting that the video was downloaded but it's impossible to play it, video is just a black screen.
Also, this code works if I use it to fetch images instead of video. Is there a limitation I'm not aware of, preventing to download Blob above a certain size? (My video is 1.5 MB).
Thanks you very much for your help!
This is most certainly a bug. If you get something that works on Desktop Chrome but not Android then 99.5% of the time it is an issue we need to fix.
I have replicated your issue http://jsbin.com/uyehun/1 and I have filed the bug too https://code.google.com/p/chromium/issues/detail?id=253465
Per http://caniuse.com/bloburls, for Android 4.0-4.3 you need to use window.webkitURL.createObjectUrl() instead of window.URL.createObjectUrl().
This will let you generate a blob url, though I haven't actually been able to get a video element to play such an url.

How can i change the XmlHttpRequest or FileAPI used in html5uploader to support IE

I perfectly integrate html5uploder in a website I developed, however it was not designed to work with IE. But the client now wants atleast IE 10 supported. Even though IE has support for FileAPI the Drag and Drop file uploader doesnt work with any IE browser.
There is no major issue with IE, this code is easily adaptable to Microsoft browser.
Make first sure that, on the html file, you force your browser to the "IE10" (or more) mode (no quirk, no compatibility mode). If not, all the javascript will fail since most of the code was not compliant with IE9:
<meta http-equiv="X-UA-Compatible" content="IE=edge">
of course, it is not taken into account in the other browsers, so no problem.
Now, lets modify a bit the html5uploader.js file:
First readAsBinaryString is not accepted in IE10. You can replace it by readAsDataURL, but this will change the way you submit your file, so also the way you have to received it (in php)
if (navigator.appName === "Microsoft Internet Explorer") {
reader.readAsDataURL(file);
} else {
reader.readAsBinaryString(file);
}
Second, sendAsBinary does not work on IE, and not relevant since we are using now readAsDataURL. So we have to submit our file as a base64 string that we will convert to binary after (in php). Just send it with xhr.send
Finally, btoa is a function implemented by Mozilla and also available in Chrome. Cannot be used in IE10 I think. But no problem, since readAsDataURL will read your file as a base64 string ! So just send it with xhr.send((bin));
So it gives:
if(xhr.sendAsBinary != null) {
xhr.sendAsBinary(body);
// Chrome and IE10 sends data but you must use the base64_decode on the PHP side
} else {
if (navigator.appName === "Microsoft Internet Explorer") {
xhr.open('POST', targetPHP+'?up=true&browser=IE&filename='+encodeURI(file.name), true);
} else {
xhr.open('POST', targetPHP+'?up=true&browser=chrome&filename='+encodeURI(file.name), true);
}
xhr.setRequestHeader('UP-FILENAME', file.name);
xhr.setRequestHeader('UP-SIZE', file.size);
xhr.setRequestHeader('UP-TYPE', file.type);
if (navigator.appName === "Microsoft Internet Explorer") {
xhr.send((bin)); // in IE, it s already base64, no need conversion
} else {
xhr.send(window.btoa(bin)); // in Chrome, it s binary, so conversion to base64 is needed
}
}
note that on the server side, I cannot get the header with getallheaders() because this function does not work on IIS and PHP 5.2, so I transfer the file name directly through the URL !
So now we have 3 cases in PHP:
Firefox will send as a binary, easy to get with $_FILES['upload']['tmp_name'] then move it.
in IE, we get $_GET['browser']=='IE'.
we get the content of the file like that:
$content = file_get_contents('php://input'); //the string we get contains 2 parts
$content = str_replace(' ','+',$content); // we need to replace spaces by plusses
$content = split(",",$content); // we do not need the first part of the string (the one with the file type).
$content = base64_decode($content[1]); // we decode the base64 to binary
in Chrome, we get $_GET['browser']=='chrome'.
we get the content of the file like that: $content = base64_decode(file_get_contents('php://input')); //easy because it is already a binary file encoded to base64, so just need to decode it !
For both IE and chrome, we create the file with:
$filename = urldecode($_GET['filename']); // because I cannot get headers...
file_put_contents($upload_folder.'\\'.$filename, $content);
DONE !
You approach works for me. I remove IE specific conditions from JS and server. It works on IE10, IE11, Chrome.
Javascript
private onFileChange(e) {
var file = _.first(e.target.files);
if (!file) { return; }
var xhr = new XMLHttpRequest();
xhr.open("POST", '/upload', true);
xhr.setRequestHeader("Session-Id", 'secret');
var reader = new FileReader();
reader.onload = function(){
xhr.send(this.result);
};
reader.readAsDataURL(file);
}
On Rails server
class UploadsController < ApplicationController
def create
file_id = DateTime.current.strftime('%Y_%m_%d_%H_%M_%S_%L') + '_' +
SecureRandom.hex
base64_content = request.body.read.to_s.split(',').last
file_content = Base64.decode64(base64_content)
File.open("tmp/#{file_id}", 'wb'){ |f| f.write(file_content) }
render json: { id: file_id }
end
end

XMLHttpRequest to read an external file

I want to retrieve the data contained in a text file (from a given URL) through JavaScript (running on the client's browser).
So far, I've tried the following approach:
var xmlhttp, text;
xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', 'http://www.example.com/file.txt', false);
xmlhttp.send();
text = xmlhttp.responseText;
But it only works for Firefox. Does anyone have any suggestions to make this work in every browser?
Thanks
IT works using xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); in IE older versions. Chrome, Firefox and all sensible browsers use xhr
Frankly, if you want cross browser compatibility, use jquery
its pretty simple there:
var text="";
$.get(url, function(data){text=data;//Do something more with the data here. data variable contains the response})
var xhr = new XMLHttpRequest();
xhr.open('POST', '/uploadFile');
var form = new FormData();
form.append('file', fileInput.files[0]);
xhr.send(form);
It was previously impossible to upload binary data with XMLHttpRequest object, because it could not stand the use of FormData (which, anyway, did not exist at that time) object. However, since the arrival of the new object and the second version of XMLHttpRequest, this "feat" is now easily achievable
It's very simple, we just spent our File object to a FormData object and upload it

Categories

Resources