I am calling AWS S3 to retrieve images using AJAX call in jQuery 3.3.0 and instead of getting a blob object, I am receiving the response as "[object Blob]". Please let me know if I have to provide further details.
Please find the code below:
$.ajax({
url: "my_path/download_image.php",
data: {
name: "my_name"
},
cache: false,
xhrFields: {
responseType: 'blob'
},
success: function (data) {
console.log(data);
var image = new Image();
var url = window.URL || window.webkitURL;
self.DownloadStudentImages(students, index + 1);
image.src = url.createObjectURL(data);
self.SavePic(imageFilename);
},
error: function () {}
});
I have fixed the issue. Usually, AWS response from PHP is in string format unless it is encoded explicitly. So, I am sending base64 from PHP and in the javascript side, I am converting it to a byte array and thus into a blob which fixes the issue.
Related
How to write output of an octet-stream to a file while the stream is being downloaded ?
I receive the stream as a blob and then download it at the end of the stream, but how to receive the
stream and write to a file ?(something like a FileStream that takes a stream and writes to a file)
AJAX code below
$.ajax({
type: "post",
url: apiURL,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(String(strCustomData)),
xhrFields: {
responseType: "blob", // <-- can also be an arrayBuffer
onprogress: function(e) { // <-- get response body here, read its stream and save in file
// TODO
}
},
cache: false,
headers: { "RequestVerificationToken": get_CSRF_TOKEN() },
success: function (response, textStatus, request) {
const requestHeaders = request.getResponseHeader("Content-Disposition") || "";
const requestContentType = request.getResponseHeader("Content-Type") || "application/zip";
const strFileName = requestHeaders?.split(";")[1]?.split("=")[1] || "File_Not_Found.zip";
const blob = response;
const url = window.URL || window.webkitURL;
const urlLink = url.createObjectURL(blob);
// create Anchor element that holds the blob and then download it as a file
const elementAnchor = document.createElement("a");
elementAnchor.setAttribute("href", urlLink);
elementAnchor.setAttribute("download", strFileName);
// download the file
elementAnchor.click();
// dispose blob object and delete it from memory
url.revokeObjectURL(urlLink);
elementAnchor.remove();
},
error: function (xhr, ajaxOptions, thrownError) {
// More validation code...
console.error(String(xhr.statusText));
}
});
I am looking for something like the anchor download tag <a asp-page-handler="apiURL" download>Download</a> where it receives a stream and downloads its without using a blob.
I would have used the anchor tag, but I need some Javascript code to be executed alongside it.(Progress bar, some required custom info to display, ...etc.)
I tried using StreamSaver.js but could not make it work in the onprogress section of the AJAX request.(how to get the response.body.getReader() in onprogress event ?how to save stream to a file without waiting for the download to complete ?)
Using JQuery inside Razor pages with Asp.Net Core.
I'm trying to write a Google Cloud Functions HTTP handler to upload audio files constructed as blobs to Google Cloud Storage from a webpage. Based on the documentation linked above I want the body of my POST request to be handled as a Node.js Buffer and I can achieve this with Content-Type: application/octet-stream. I'm sending the request from a webpage that has this xhr request:
// where `var blob` is a Blob of type "audio/wav"
// and size of > 0 generated from the
// WebAudioAPI
var fileReader = new FileReader();
fileReader.onloadend = function() {
$.ajax({
type: 'POST',
url: GOOGLE_CLOUD_FUNCTION_URL,
data: this.result,
dataType: 'json',
processData: false,
contentType: 'application/octet-stream',
success: function(resp) {
},
error: function(err) {
}
});
};
fileReader.readAsArrayBuffer(blob);
and my Google Cloud Functions module looks like this:
exports.upload = function(req, resp) {
resp.header('Content-Type','application/json');
resp.header('Access-Control-Allow-Origin', req.get('origin'));
resp.header('Access-Control-Allow-Headers', 'Content-Type');
switch (req.method) {
case 'POST':
response.status(200).send({
contentType: request.get('content-type'),
body: request.body,
rawBody: request.rawBody
});
break;
}
};
The request header shows that that there is data being attached. But, the content-type is not set as `application/octet-stream'. In addition the response returns:
{
body: {}
}
What is the JavaScript type of data to pass to an ajax body for the Google Cloud Functions HTTP handler accept the body as a Buffer?
Blob, File, Typed Array, Array Buffer?
In an Express app, I have a simple image uploader which was working perfectly using Ajax PUT requests. But now I need to crop the images before sending them to the server.
I plugged in Croppie to help with this. On form submit I get the cropped image blobs from Croppie, convert them to files, append the files to the Ajax FormData object, and send the FormData off to Express.
But the server isn't receiving and files, and examining the PUT request in Chrome's dev tools shows that no file info is being send.
I've console.logged the blobs and the files, and as far as I can tell they are being created properly.
Getting the blobs and converting them to files:
var fileList = []
if($croppieContainers.length > 0){
$.each($croppieContainers, function(i){
$(this).croppie('result', {
type: 'blob', // Get the blob from the croppie container
}).then(function(blob) {
let file = new File([blob], "image-" + i, {
type: blob.type,
lastModifiedDate: new Date(); // Make a file from the blob...
});
fileList.push(file) // And push it to fileList
});
});
}
Appending the files to ajaxData:
if(fileList.length > 0) {
$.each('fileList', function(file){
ajaxData.append($input.attr('name'), file);
})
}
posting to Express:
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: ajaxData,
// dataType: 'json',
cache: false,
contentType: false,
processData: false,
complete: function() {
$form.removeClass('is-uploading');
},
success: function(data) {
// Handlers...
Console.log(blob) returns:
Blob
size:288345
type: "image/png"
__proto__: Blob
And the file:
File
lastModified : 1478972364233
lastModifiedDate : Sat Nov 12 2016 17:39:24 GMT+0000 (GMT)
name : "image-0"
size : 288345
type : "image/png"
webkitRelativePath : ""
__proto__ : File
I've tried getting the file a different way, but it gives the same result:
if($croppieContainers.length > 0){
$.each($croppieContainers, function(i){
let file = new File([$(this).croppie('result', {
type: 'blob'}
)],
"image-" + i)
ajaxData.append($input.attr('name'),file)
});
}
I'm note sure how to debug this, apart from console.logging at various stages, and checking the XHR in dev tools...
Can anyone see what the problem is, or tell me how I can debug further?
Thanks you!
i'm trying encode the document generated in the attached code, but nothing happens, not generate error but neither encodes the file, and the ajax request is never executed
what is the correct way?
html2canvas(document.getElementById("workAreaModel"), {
onrendered: function(canvas)
{
var img = canvas.toDataURL("image/png");
var doc = new jsPDF("l", "pt", "letter");
doc.addImage(img, 'JPEG',20,20);
var fileEncode = btoa(doc.output());
$.ajax({
url: '/model/send',
data: fileEncode,
dataType: 'text',
processData: false,
contentType: false,
type: 'GET',
success: function (response) {
alter('Exit to send request');
},
error: function (jqXHR) {
alter('Failure to send request');
}
});
}
});
First, jsPDF is not native in javascript, make sure you have included proper source, and after having a peek on other references, I think you don't need btoa() function to convert doc.output(), just specify like this :
doc.output('datauri');
Second, base-64 encoded string is possible to contain ' + ' , ' / ' , ' = ', they are not URL safe characters , you need to replace them or you cannot deal with ajax .
However, in my own experience, depending on file's size, it's easy to be hell long ! before reaching the characters' length limit of GET method, encoded string will crash your web developer tool first, and debugging would be difficult.
My suggestion, according to your jquery code
processData: false,
contentType: false
It is common setting to send maybe File or Blob object,
just have a look on jsPDF, it is availible to convert your data to blob :
doc.output('blob');
so revise your code completely :
var img = canvas.toDataURL("image/png");
var doc = new jsPDF("l", "pt", "letter");
doc.addImage(img, 'JPEG',20,20);
var file = doc.output('blob');
var fd = new FormData(); // To carry on your data
fd.append('mypdf',file);
$.ajax({
url: '/model/send', //here is also a problem, depends on your
data: fd, //backend language, it may looks like '/model/send.php'
dataType: 'text',
processData: false,
contentType: false,
type: 'POST',
success: function (response) {
alter('Exit to send request');
},
error: function (jqXHR) {
alter('Failure to send request');
}
});
and if you are using php on your backend , you could have a look on your data information:
echo $_FILES['mypdf'];
This code is for capturing Html page from screen and save as Pdf and send to back end api As blob
const filename = 'form.pdf';
const thisData = this;
this.printElement = document.getElementById('content');
html2canvas(this.printElement).then(canvas => {
this.pdfData = new jsPDF ('p', 'mm', 'a4');
this.imageHeight = canvas.height * 208 / canvas.width;
this.pdfData.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0, 208, this.imageHeight);
this.pdfData.save(filename);
this.uploadFile(this.pdfData.output('blob'));
});
}
uploadFile(pdfFile: Blob) {
this.uploadService.uploadFile(pdfFile)
.subscribe(
(data: any) => {
if (data.responseCode === 200 ) {
//succesfully uploaded to back end server
}},
(error) => {
//error occured
}
)
}
I am working on a simple chrome-extension that needs to upload files to the user's dropbox folder. I am using the simple AJAX requests as mentioned below to upload files, however it works for files with extensions such as .txt, .json, .c, etc i.e. files whose mime type is of type text/plain or similar type but all other file types such as pdfs, image files etc get corrupted and produce blank contents. What am I missing in uploading the files the correct way.
function startUpload()
{
var folderPath = $(this).closest('tr').attr('path')+'/';
var file = $("#upload_file")[0].files[0];
if (!file){
alert ("No file selected to upload.");
return false;
}
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
uploadFile(folderPath+file.name,evt.target.result,file.size,file.type);
}
}
//function to upload file to folder
function uploadFile(filepath,data,contentLength,contentType){
var url = "https://api-content.dropbox.com/1/files_put/auto"+filepath;
var headers = {
Authorization: 'Bearer ' + getAccessToken(),
contentLength: contentLength,
};
var args = {
url: url,
headers: headers,
crossDomain: true,
crossOrigin: true,
type: 'PUT',
contentType: contentType,
data : data,
dataType: 'json',
success: function(data)
{
getMetadata(filepath.substring(0,filepath.lastIndexOf('/')),createFolderViews);
},
error: function(jqXHR)
{
console.log(jqXHR);
}
};
$.ajax(args);
}
I believe the issue is reader.readAsTextFile(file, "UTF-8"). If the file isn't a text file, this will misinterpret the contents. I think you want reader.readAsBinaryString or reader.readAsArrayBuffer. (I haven't tested it myself.)
EDIT
After testing this myself, I found that readAsArrayBuffer is what you need, but you also need to add processData: false as an option to $.ajax to prevent jQuery from trying to convert the data to fields in a form submission.
Also be sure to use dataType: 'json' to properly parse the response from the server.