jQuery Ajax - downloading incomplete (binary) file - javascript

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

Related

Make an API call from JavaScript

I'm attempting to make a call to an API, which takes requests in the form of Mongodb's '.find' method.
Using postman I can make the following call and I get the correct response.
http://asterank.com/api/asterank?query={"full_name": {"$eq" : "(2004 EU22)"}}&limit=5
But, when I try to make the same call in JavaScript, my entire web application just shows a blank webpage. So is the following way of utilizing a mongodb call wrong?
var example = "0";
function getAsterank(){
//ARRAY OF NEO NAMES
var xhr = new XMLHttpRequest();
xhr.open("GET", 'http://asterank.com/api/asterank?query={"full_name": {"$eq" : "(2004 EU22)"}}&limit=5', false);
xhr.send(null)
responseData = JSON.parse(xhr.response);
xhr.abort();
example = responseData;
}
If I make this same exact JS call using a different api such as the following, it works just fine. I use sublime text so I don't think I can debug it to see whats actually happening.
v
ar MeMe = "0";
function getAsterank(){
//ARRAY OF NEO NAMES
var xhr = new XMLHttpRequest();
xhr.open("GET", 'https://api.nasa.gov/neo/rest/v1/feed/today?detailed=true&api_key=NnRe38qGPTpKPtsenpkqROMTtXvkWnVNyql9lmnP', false);
xhr.send(null)
responseData = JSON.parse(xhr.response);
xhr.abort();
MeMe = responseData;
}
if jquery is an option this might be a solution
$(document).ready(function(){
$(".submitBottom").click( function() {
$.ajax({
type: "GET",
url: 'http://asterank.com/api/asterank?query={"full_name":{"$eq":"(2004 EU22)"}}&limit=5',
encode: true,
success: function (data) {
console.log("success", data)
}
});
});
});

Match a curl request to NancyFx service from browser js

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

Why does AJAX output comes with wrong encoding?

I'm getting a file from a server with AJAX (Angular).The file is a simple XLSX document, sent like this:
ob_start();
$file = \PHPExcel_IOFactory::createWriter($xls, 'Excel2007');
$file->save('php://output');
$response->setContent(ob_get_clean());
$response->headers->replace(array(
'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'Content-Disposition' => 'attachment;filename=file.xlsx"'
));
When I make a request from frontend, I use Accept header too. Then I save the file with angular-file-saver using FileSaver.js and Blob.js.
But the received file is corrupt and I can't open it in Excel: it's size is (for example) 12446 bytes, but Chrome's DevTools Network tab shows responses Content-Length header as 7141 bytes.
How can I solve this problem?
UPD:
I'm sending a request like this:
$http.get(baseURL + '/' + entity + '/export/?' + condition + sort, {
headers: {'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8'}
});
and downloading file just like this:
var data = new Blob([response.data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'});
FileSaver.saveAs(data, 'file.xlsx');
The way I got around the problem was using plain JS AJAX, instead of AngularJS. (There might be a problem with AngularJS and JQuery handling binary responses.)
This should work:
var request = new XMLHttpRequest();
request.open('GET', 'http://yourserver/yourpath', true);
request.responseType = 'blob';
request.onload = function (e) {
if (this.status === 200) {
var blob = this.response;
if (window.navigator.msSaveOrOpenBlob) {
var fileNamePattern = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
window.navigator.msSaveBlob(blob, fileNamePattern.exec(request.getResponseHeader("content-disposition"))[1]);
} else {
var downloadLink = window.document.createElement('a');
var contentTypeHeader = request.getResponseHeader("Content-Type");
var b = new Blob([blob], { type: contentTypeHeader });
downloadLink.href = window.URL.createObjectURL(b);
var fileNamePattern = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
downloadLink.download = fileNamePattern.exec(request.getResponseHeader("content-disposition"))[1];
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
window.URL.revokeObjectURL(b);
}
}
};
request.send();
Code is based on this and this.
FYI, I found that new Blob([response.data], ...) returns almost double the size of response.data when response.data is not returned as blob, but text/plain or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet. To get around it, you need to pass it an array of bytes instead:
var i, l, d, array;
d = this.result;
l = d.length;
array = new Uint8Array(l);
for (var i = 0; i < l; i++){
array[i] = d.charCodeAt(i);
}
var b = new Blob([array], {type: 'application/octet-stream'});
window.location.href = URL.createObjectURL(b);
Code is from here.
Anyways, since the AJAX response is not correct using AngularJS, you won't get a valid xlsx file this way. You need to go with vanilla JS.

jQuery not working when sending sync XMLHttpRequest

I have this code which sends a string into chuncks.
Everything is OK expect that when the script is posting to the server #status doesn't update.
The request is sync and not async because I want to post one chunk at a time and not everything at onces.
for (var packet in packets) {
var calculated = ((packet/(packets_lenght-1))*100);
$('#status').text(calculated);
var formData = new FormData();
formData.append("packet", packets[packet]);
formData.append("packet_num", packet);
formData.append("name", 'name');
var request = new XMLHttpRequest();
request.open("POST", "index.php", false);
request.send(formData);
}
Can someone tell me what I am doing wrong?
Thanks.
That is because browser didn't refresh view state while he is busy by execution code ( js executed in single threat - so in case of sync requests - ints normal )
you should async iterations over array like this http://jsfiddle.net/7TzF8/
Sorry - z made minor changes to just show idea, you can refactor your code according main idea
var packets = str2chunk(JSON.stringify(frames_array).split('data:image/jpeg;base64,').join(''), 10);
var packets_lenght = packets.length;
function processPacket(packet){
if(packet >= packets_lenght){
return;
}
$.ajax({
type: "POST",
url: "http://fiddle.jshell.net/echo/jsonp/",
data: {
packet: packets[packet],
packet_num: packet,
name: 'name'
},
success: function (answer) {
console.log(packet);
var calculated = ((packet / (packets_lenght - 1)) * 100);
$('#status').text(calculated + '%');
processPacket(packet+1);
},
error: function () {
}
});
}
processPacket(0);

Download Binary Data as a File Via Javascript

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

Categories

Resources