I'm making an ajax call to an API that returns binary data. I'm wondering if its possible to take that binary data and display it for the client in a new window? This is what I'm doing right now. The problem is, the document opens up, but its completely blank.
$.ajax({
type: "POST",
url: apiURL,
data: xmlRequest,
complete: function(xhr, status) {
var bb = new window.WebKitBlobBuilder();
// Append the binary data to the blob
bb.append(xhr.responseText);
var blobURL = window.webkitURL.createObjectURL(bb.getBlob('application/pdf'));
window.open(blobURL);
}
});
Any ideas?
Okay, I figured it out. I had to specify the responseType as 'array buffer':
function downloadPDF() {
var xhr = new XMLHttpRequest();
xhr.open('POST', API_URL, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var bb = new window.WebKitBlobBuilder();
bb.append(this.response); // Note: not xhr.responseText
var blob = bb.getBlob('application/pdf');
var blobURL = window.webkitURL.createObjectURL(blob);
window.open(blobURL);
}
};
xhr.send(createRequest());
}
Related
An image file is sent from ASP.Net MVC using FilePathResult. How can this image be converted into a base64 string at client side (web browser) when http response is received. It is showing data in the raw form in response.data object. I've tried
var blob = new Blob([response.data], { type: 'image/jpeg' });
var reader = new FileReader();
reader.onloadend = function () {
var base64data = reader.result;
console.log(base64data);
}
reader.readAsDataURL(blob);
When you fetch the binary as text with ajax, browsers will try to parse the character set and change your data.
You must fetch the data as a blob to avoid to tell them not to
function getBase64(blob) {
var blob = xhr.response
var reader = new FileReader();
reader.onload = function () {
var base64data = reader.result;
console.log(base64data);
}
reader.readAsDataURL(blob);
}
var xhr = new XMLHttpRequest()
xhr.open('GET', '/myfile.png', true)
xhr.responseType = 'blob' // get data as blob
xhr.onload = function() {
getBase64(xhr.response)
}
xhr.send()
// or if you are using fetch
fetch('/myfile.png')
.then(function(res) {
res.blob() // get data as blob
.then(getBase64)
})
I hope I am not misunderstood:
Try this script, for the easier ajax I'm using jquery:
$.ajax({
url: 'someImage.png',
type: 'POST',
success: function(r) {
var data = btoa(r);
$('img.photo').attr('src', "data:image/png;base64," + data);
},
});
you can change above code as you need.
I'm having troubles instantiating a new file object in javascript.
Here's the general gist of what I'm trying to do. There is client side code that expecting a "file" type object. I need to access the file that's located on the server (game.smc), download it to the local machine and feed it to the client side code.
I did some research and found that creating a new blob object is the first step. But in the code below the blob object remains null and is never getting populated. Does the path in the xhr.open need to have the entire url? Maybe i'm missing an entire concept here not sure.
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", "/Roms/game.smc");
xhr.responseType = "blob";
xhr.onload = function()
{
blob = xhr.response;
}
xhr.send();
Once I can get the blob object populated I can then do this to convert it to a file object.
function blobToFile(theBlob, fileName) {
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
This is what I ended up doing. Shows how to get the blob object as well as convert it to a file type.
function autoLoadGame(fileName) {
var gameLocation = '/Content/Roms/Snes/' + fileName;
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", gameLocation, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
var blob = xhr.response;
var file = new File([blob], fileName, { type: '', lastModified: Date.now() });
snes_readfile(file);
}
}
xhr.responseType = "blob";
xhr.send();
}
I've got a microservice (in NancyFx) that works as expected for the following cURL command:
curl --verbose --form file=#"C:\test\image.png" http://localhost:8080/file/upload
The file shows up inside Nancy as expected at:
context.Request.Files[0] //The file bytes are here, yeah!!
Now I've got to get my web-client to send a selected file to the same service, in the same way.
TLDR; You can skip my failure examples below if you'd like
I've tried several versions of the following with no success:
var uploadForm = new FormData();
// Add the file to the request.
uploadForm.append("file", file, name);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:8080/file/upload', true);
xhr.onload = function() {
if (xhr.status === 200)
alert('File ' + name + 'Upload successfully!!!');
else errorFn("Upload Failure on file " + name);
};
//Send the data
xhr.send(uploadForm);
and several versions of the following, also with no success:
var postConfig = {
url: 'http://localhost:8080/file/upload',
data: uploadForm,
processData: false, //tries without this as well
type: "POST",
dataType: "application/x-www-form-urlencoded; charset=UTF-8",
cache: false,
success: successFn,
error: errorFn
}
$.ajax(postConfig);
I've tried the above with
file = direct reference to $('MyFileSelectorControl').files[0]
file being set with the following code:
var reader = new FileReader();
reader.onload = function (result) {
var fileContent = new Uint8Array(result.target.result);
var encContent = new SP.Base64EncodedByteArray();
for (var b = 0; b < fileContent.length; b++) {
encContent.append(fileContent[b]);
}
<Set file = encContent and send AJAZ as above>
};
reader.readAsArrayBuffer(fileInput);
Setting file = to fileContent above (IOW, after it has been through the reader, but not encoded.)
How do I submit this file from javascript (jQuery or standard) so that it works like it does from cURL?
Here is the code that finally worked. (Admittedly, I had thought I had already tried this and said so in my question)
var file = $('MyFileSelectorControl').files[0];
var uploadForm = new FormData();
// Add the file to the request.
uploadForm.append("file", file, name);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:8080/file/upload', true);
xhr.onload = function() {
if (xhr.status === 200)
alert('File ' + name + 'Upload successfully!!!');
else errorFn("Upload Failure on file " + name);
};
//Send the data
xhr.send(uploadForm);
I am posting some data to server through Backbone.js and server sends a csv file as response. As Backbone.js handles only json format can some body tell me how to handle this case, so that i would be able to download the csv file gracefully.
object = {};
object.c1 = formObj.c1
hash = {
success: function(model, response, options) {
},
error: function(model, response, options) {
return console.log(response);
}
};
model = new P.models.mine(object);
model.doSomething(object, hash);
It always comes to error part.
The ideal way to handle this would be to change your back end code to return JSON, or create another route that returns JSON. Since you are asking this question I'm assuming that isn't an option for you.
Basically you are going to have to parse the CSV on the client side:
https://stackoverflow.com/a/1293163/944006 - Should get you started.
If you are asking to download a csv file, then just pointing the browser at the location should prompt the user for download. You cannot prompt a file download through ajax(for good reason), but there are ways to tiptoe around this limitation:
https://stackoverflow.com/a/9970672/944006
You could also use plain javascript rather than Backbone.js. Believe me this is the best way.
Here is some code:
var xhr = new XMLHttpRequest();
xhr.open('POST', Urls.download, true);
xhr.responseType = 'blob';
xhr.setRequestHeader("Authorization", "Bearer " + access_token);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.onload = function (e) {
if (this.status == 200) {
var blob = new Blob([this.response], { type: 'application/vnd.ms-excel' });
var downloadUrl = URL.createObjectURL(blob);
var a = document.createElement("a");
a.id = "a" + new Date().getTime();
a.setAttribute("data-bypass", "");
a.href = downloadUrl;
a.download = "list_" + new Date().getTime() + ".xlsx";
document.body.appendChild(a);
a.click();
} else {
alert('Unable to download excel.')
}
};
xhr.send(JSON.stringify(this.obj));
This is what I have:
jquery/1.10.2
$.ajax({
url: "http://samplepdf.com/sample.pdf",
dataType: "text",
data: "",
success: function(data) {
alert(data.length);
},
error: function(a, b, c) {}
});
When I run that locally (in Safari 6.0.5 on OS X), I get 211300. However, the actual file appears to be 218882 bytes. With something fully ASCII (such as http://www.angio.net/pi/digits/pi1000000.txt), it seems to work correctly.
I don't need to download the file, but rather, work with its content.
Is there any way to make ajax work with binary files (either client side or server side) without resorting to using base64?
I think you need to use typed arrays. Javascript way of dealing with binary.
There is no other way to deal with pure binary data. But with typed arrays you can do almost everything that you would want to do with binary anywhere else.
Sending Typed Array using Ajax
var myArray = new ArrayBuffer(512);
var longInt8View = new Uint8Array(myArray);
for (var i=0; i< longInt8View.length; i++) {
longInt8View[i] = i % 255;
}
var xhr = new XMLHttpRequest;
xhr.open("POST", url, false);
xhr.send(myArray);
Receiving Typed Array
2 ways to do it...First
var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
var arrayBuffer = oReq.response; // Note: not oReq.responseText
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteArray.byteLength; i++) {
// do something with each byte in the array
}
}
};
oReq.send(null);
Second
var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "arraybuffer";
oReq.onload = function(oEvent) {
var blob = new Blob([oReq.response], {type: "image/png"});
// ...
};
oReq.send();
Source: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
Using Jquery
Sending: $.ajax(url,{data:myArray});
Receiving: not tested...
$.ajax('https://dl.dropboxusercontent.com/u/139992952/coffee.png',{
contentType: "arraybuffer",
success: function(d){
var blob = new Blob([d], {type: "image/png"}),
u = URL.createObjectURL(blob);
}
});
The worst wheel of the cart makes the most noise!
go for a better solution here
http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/
Demo here
http://jqueryfiledownload.apphb.com/
Fully tested on:
Internet Explorer 6 – 9
Firefox 11 – reasonably sure it will work on earlier versions
Chrome 17 – reasonably sure it will work on earlier versions
Remark : jQuery 1.3+ needed.
update:
Haven't tried though
$.ajax({
url: controllerUrl,
type: 'Get',
contentType: "application/pdf",
beforeSend: function (xhr) {
xhr.overrideMimeType('text/plain; charset=UTF-8')
//alert({ message: "Processing..." });
},
success: function (data)
{ alert('Wga!');
},
complete: function (data) {
alert('close');
},
error: function (jqXHR,textStatus)
{ alert("whoops"); }