I'm getting an InvalidStateError at the blob creation line on IE 11. Needless to say, it works in Chrome and Firefox.
I can see that the binary data is my client side. Are there any alternatives to download this as a file?
var request = new ActiveXObject("MicrosoftXMLHTTP");
request.open("post", strURL, true);
request.setRequestHeader("Content-type", "text/html");
addSecureTokenHeader(request);
request.responseType = 'blob';
request.onload = function(event) {
if (request.status == 200) {
var blob = new Blob([request.response], { type: 'application/pdf' });
var url = URL.createObjectURL(blob);
var link = document.querySelector('#sim');
link.setAttribute('href', url);
var filename = request.getResponseHeader('Content-Disposition');
$('#sim').attr("download", filename);
$(link).trigger('click');
fireEvent(link, 'click');
} else {
// handle error
}
}
After instantiating an XmlHttpRequest with xhr.responseType = "blob"
I was getting an InvalidStateError.
However, moving xhr.responseType = "blob" to onloadstart solved it for me! :)
xhr.onloadstart = function(ev) {
xhr.responseType = "blob";
}
Spent some time on this and actually found out adding new Uint8Array works:
var blob = new Blob([new Uint8Array(request.response)], {type: 'application/pdf'});
Is not a elegant way but it works on IE8 - IE11:
var myForm = document.createElement("form");
myForm.method = "POST";
myForm.action = strURL;
myForm.target = "_blank";
var myInput = document.createElement("input");
myInput.type = "text";
myInput.name = "sim";
myInput.value = JSON.stringify(/*data to post goes here*/);
myForm.appendChild(myInput);
document.body.appendChild(myForm);
myForm.submit();
$(myForm).hide();
You need to use a BlobBuilder in that case.
From: https://github.com/bpampuch/pdfmake/issues/294#issuecomment-104029716
try {
blob = new Blob([result], { type: 'application/pdf' });
}
catch (e) {
// Old browser, need to use blob builder
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if (window.BlobBuilder) {
var bb = new BlobBuilder();
bb.append(result);
blob = bb.getBlob("application/pdf");
}
}
After much searching this worked for me on IE, Edge and Chrome
var xhr = new XMLHttpRequest();
xhr.onloadstart = function (ev) {
xhr.responseType = "blob";
};
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
if (!window.navigator.msSaveOrOpenBlob) {
var url = (window.URL || window.webkitURL).createObjectURL(xhr.response);
var aLink = document.createElement("a");
document.body.appendChild(aLink);
aLink.href = url;
aLink.download = filename;
aLink.click();
} else {
var fileData = [xhr.response];
blobObject = new Blob(fileData);
window.navigator.msSaveOrOpenBlob(blobObject, filename);
}
}
};
Related
I am using below code to download the file to browser.
function UserAction() {
var Url = " ";
var postData = new FormData();
var xhr = new XMLHttpRequest();
xhr.open('GET', Url, true);
xhr.responseType = 'blob';
xhr.onload = function (e) {
var blob = xhr.response;
this.saveOrOpenBlob(blob,blobName);
}.bind(this)
xhr.send(postData);
}
function saveOrOpenBlob(blob,blobName) {
//var assetRecord = this.getAssetRecord();
var fileName = blobName;
var tempEl = document.createElement("a");
document.body.appendChild(tempEl);
tempEl.style = "display: none";
url = window.URL.createObjectURL(blob);
tempEl.href = url;
tempEl.download = fileName;
tempEl.click();
window.URL.revokeObjectURL(url);
}
I want to display the download progress, I am not using any html code. My application has standard button which accept javascript action. I dont have any custom ui.
With current condition user will not know whether the file is downloading or not if it is a large file.
How can I achieve this?
Use this:
function saveOrOpenBlob(url, blobName) {
var blob;
var xmlHTTP = new XMLHttpRequest();
xmlHTTP.open('GET', url, true);
xmlHTTP.responseType = 'arraybuffer';
xmlHTTP.onload = function(e) {
blob = new Blob([this.response]);
};
xmlHTTP.onprogress = function(pr) {
//pr.loaded - current state
//pr.total - max
};
xmlHTTP.onloadend = function(e){
var fileName = blobName;
var tempEl = document.createElement("a");
document.body.appendChild(tempEl);
tempEl.style = "display: none";
url = window.URL.createObjectURL(blob);
tempEl.href = url;
tempEl.download = fileName;
tempEl.click();
window.URL.revokeObjectURL(url);
}
xmlHTTP.send();
}
I have a method in JavaScript to read from a binary file into an ArrayBuffer and send it to a Jersey POST method:
function readAndSendBytes() {
var file = document.getElementById("entityFileField").files[0],
reader = new FileReader();
var entityBytes = reader.readAsArrayBuffer(file);
reader.onloadend = function () {
alert(reader.result);
}
var xhr = new XMLHttpRequest();
var url = "/api/upload/e2j";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", "application/octet-stream");
xhr.responseType = "json";
xhr.onload = function (e) {
var response = xhr.response;
alert(response);
}
xhr.send(reader.result);
}
Jersey:
#Path("/upload")
public class ParserHandler {
#POST
#Path("/e2j")
#Consumes(MediaType.APPLICATION_OCTET_STREAM)
#Produces(MediaType.APPLICATION_JSON)
public String entityToJsonTwoElectricBoogaloo(byte[] entityPayload) {
System.out.println(entityPayload.length);
}
Whenever I print length to the console, the length is always 0, when it should be 439. What am I doing wrong?
there is no need to use the filereader, you can just send the blob with xhr
function sendFile() {
var file = document.getElementById("entityFileField").files[0];
var xhr = new XMLHttpRequest();
var url = "/api/upload/e2j";
xhr.open("POST", url);
xhr.setRequestHeader("Content-type", "application/octet-stream");
xhr.responseType = "json";
xhr.onload = function (e) {
var response = xhr.response;
alert(response);
}
xhr.send(file);
}
Found the solution! Just moved everything but send and initialisations of file and FileReader into the xhr.onload function!
EDIT: Forgot to post my solution.
function postEntity() {
var output = document.getElementById("response");
var file = document.getElementById("entityFileField").files[0];
var jsonResponse;
var r = new FileReader();
r.onloadend = function(e) {
var data = r.result;
var xhr = new XMLHttpRequest();
var url = "/api/upload/entitytojson";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", "application/octet-stream");
xhr.responseType = "json";
xhr.onload = function (e) {
if (xhr.response != null) {
jsonResponse = JSON.stringify(xhr.response);
output.innerHTML = jsonResponse;
}
else {
alert("Invalid Entity File");
}
}
xhr.send(data);
}
r.readAsBinaryString(file);
}
I'm trying to convert an image (link) to base64 to be able to store in the Browser side (IndexedDB), but i'm not able to do that, I have been looking for a solution for days and I didn't a solution to my problem.
In this awesome code I'm able to convert an image from internet to Base64, but the problem is that I can't do that for other images on internet because of the Same-origin policy.
How I would be able to avoid that problem or if you know any other solution to convert an image to Base64, that would be really helpful
function convertImgToBase64URL(url, callback, outputFormat){
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
var canvas = document.createElement('CANVAS'),
ctx = canvas.getContext('2d'), dataURL;
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
dataURL = canvas.toDataURL(outputFormat);
callback(dataURL);
canvas = null;
};
img.src = url;
}
convertImgToBase64URL('http://upload.wikimedia.org/wikipedia/commons/4/4a/Logo_2013_Google.png', function(base64Img){
alert('it works');
$('.output').find('img').attr('src', base64Img);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="output"> <img> </div>
While converting into base64 you can use a proxy URL (https://cors-anywhere.herokuapp.com/) before your image path to avoid cross-origin issue
var getDataUri = function (targetUrl, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var reader = new FileReader();
reader.onloadend = function () {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
xhr.open('GET', proxyUrl + targetUrl);
xhr.responseType = 'blob';
xhr.send();
};
getDataUri(path, function (base64) {
// base64 availlable here
})
You need to download the image to a byte array first:
Downloading binary data using XMLHttpRequest, without overrideMimeType
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.celticfc.net/images/doc/celticcrest.png', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var uInt8Array = new Uint8Array(this.response); // Note:not xhr.responseText
for (var i = 0, len = uInt8Array.length; i < len; ++i) {
uInt8Array[i] = this.response[i];
}
var byte3 = uInt8Array[4]; // byte at offset 4
}
}
xhr.send();
Then you can use the byte array as follows: Javascript : How to display image from byte array using Javascript or Servlet?
<img id="ItemPreview" src="" />
document.getElementById("ItemPreview").src = "data:image/png;base64," + YourByteArray;
EDIT: I cannot try this ATM but you can alternatively save the file to the file system using the HTML5 FileSystem API: How to save a image to HTML5 filesystem with the url of image
window.requestFileSystem(window.PERSISTENT, 2*1024*1024, onFileSystemSuccess, fail);
function onFileSystemSuccess(fileSystem) {
fs = fileSystem;
console.log('File system initialized');
saveAsset('http://www.example-site-with-cors.com/test.png');
}
function saveAsset(url, callback, failCallback) {
var filename = url.substring(url.lastIndexOf('/')+1);
// Set callback when not defined
if (!callback) {
callback = function(cached_url) {
console.log('download ok: ' + cached_url);
};
}
if (!failCallback) {
failCallback = function() {
console.log('download failed');
};
}
// Set lookupTable if not defined
if (!window.lookupTable)
window.lookupTable = {};
// BlobBuilder shim
// var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
// xhr.responseType = 'blob';
xhr.responseType = 'arraybuffer';
xhr.addEventListener('load', function() {
fs.root.getFile(filename, {create: true, exclusive: false}, function(fileEntry) {
fileEntry.createWriter(function(writer) {
writer.onwrite = function(e) {
// Save this file in the path to URL lookup table.
lookupTable[filename] = fileEntry.toURL();
callback(fileEntry.toURL());
};
writer.onerror = failCallback;
// var bb = new BlobBuilder();
var blob = new Blob([xhr.response], {type: ''});
// bb.append(xhr.response);
writer.write(blob);
// writer.write(bb.getBlob());
}, failCallback);
}, failCallback);
});
xhr.addEventListener('error', failCallback);
xhr.send();
return filename;
}
function fail(evt) {
console.log(evt.target.error.code);
}
for same origin policy you must add headers for server side from where you want your images
here is how to do this -
http://enable-cors.org/server.html
for development purpose you can install 'CORS' extension in CHROME browser to allow cross origin request
hope this helps and solve your issue.
i need a JavaScript to download a group of images.
It should download some like this:
01.jpg
02.jpg
03.jpg....
but i get default file name:
5cEDZLQ.jpg
5Npv209.jpg
5FgtD69.jpg...
here my function to download:
function SaveToDisk(fileURL, fileName) {
var save = document.createElement('a');
save.href = fileURL;
save.target = '_blank';
save.download = fileName;
var event = document.createEvent('Event');
event.initEvent('click', true, true);
save.dispatchEvent(event);
window.webkitURL.revokeObjectURL(save.href);
}
tried various ways, but always download with the default name
Well is a long time but here is the solve.
Dowload the image/file using XMLHttpRequest and pass the result to the function saveAs from FileSaver.js
Example:
var xhr = new XMLHttpRequest();
var url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/272px-Google_2015_logo.svg.png';
var name = 'Google Logo.png';
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onprogress = function(e) {
if (e.lengthComputable) {
console.log( ((e.loaded / e.total) * 100) + '%');
}
};
xhr.onload = function() {
if (this.status === 200) {
var file = this.response;
saveAs(file, name);
console.log('File Saved!!!')
}
};
xhr.onerror = function(e) {
alert("Error " + e.target.status + " occurred while receiving the document.");
};
xhr.send();
I want to download binary files using Javascript.
I have a REST service that returns the binary data and i want to know if its possible to show the binary file, whichever the file extension.
This is my current code:
var xhr = new XMLHttpRequest;
xhr.open("GET", requestUrl);
xhr.addEventListener("load", function () {
var ret = [];
var len = this.responseText.length;
var byte;
for (var i = 0; i < len; i++) {
byte = (this.responseText.charCodeAt(i) & 0xFF) >>> 0;
ret.push(String.fromCharCode(byte));
}
var data = ret.join('');
data = "data:application/pdf;base64," + btoa(data);
window.open(data, '_blank', 'resizable, width=1020,height=600');
}, false);
xhr.setRequestHeader("Authorization", "Bearer " + client.accessToken);
xhr.overrideMimeType("octet-stream; charset=x-user-defined;");
xhr.send(null);
Thanks!
Have a look at the MDN article on XMLHttpRequest.
If you set the response of the XMLHttpRequest to ArrayBuffer you could do the following:
var xhr = new XMLHttpRequest();
xhr.open("GET", requestUrl);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
if (this.status === 200) {
var blob = new Blob([xhr.response], {type: "application/pdf"});
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}
};
xhr.send();
Option 2:
You could use Blob as the response of the XMLHttpRequest. And then maybe save it in the FileSystem (FileSystem API)
It may look like:
var xhr = new XMLHttpRequest();
xhr.open("GET", requestUrl);
xhr.responseType = "blob";
xhr.onload = function () {
onDownloaded(this);
};
xhr.send();
Option 3:
If you only want to download and "show" images you can easily do this like so:
var img = new Image();
// add the onload event before setting the src
img.onload = function() {
onImageDownloaded(img);
}
// start the download by setting the src property
img.src = requestUrl