error in uploading file data via jQuery Ajax POST request - javascript

I am receiving an error trying to upload large than 50kB file via jQuery Ajax POST request.
I am sending the request to OData service ( ASP.Net MVC application)
The error I am receiving in browser console is " 413 Request Entity Too Large "
Below is the code I am using to upload
var fileData =
{
fileBinaryData: encodedData //file data in encoded format ( 64 bit),
Description: "my first file"
};
fileData = JSON.stringify(fileData);
$.ajax({
url: // some odata url ,
type: "POST",
data: fileData,
success: function (res) {
// do something
},
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Accept", "application/json");
}
});
a) Is code above the correct way to upload file data via jQuery ajax to a service
b) I have modified my web.config to accept large requests.
c) I do not want to use plugin's like uploadify etc
EDIT 1:
I used javascripts' FileReader() to read the file.
var reader = new FileReader();
//then applied reader.onloadend method etc
if (file.webkitSlice) {
var blob = file.slice(start, stop + 1);
} else if (file.mozSlice) {
var blob = file.mozSlice(start, stop + 1);
}
reader.readAsBinaryString(blob);

Finally settled with using jQuery fileUpload plugin

Related

Why is ajax not passing through image file?

For some reason, when I don't use Ajax, the image file in the form being processed comes through just fine, but not when using the Ajax script below.
Can't figure out why...
Note: Not all form fields are image files (there are some text fields).
jQuery.ajax({
method: 'POST',
url: 'actions/listings-add.php',
data: $('#form').serialize(),
dataType:'json',
success: function(msg){
if(parseInt(msg.status)==1)
{
window.location=msg.txt;
}
else if(parseInt(msg.status)==0)
{
error(1,msg.txt);
}
}
});
JSON does not work with "file" inputs, because they need to be transfered with multipart/form-data.
To upload files using AJAX, you can either use FormData to also transfer the file input or if you have a normal rest api that follows a standard endpoint use javascript to base64 encode the image into a string and then transfer it using your ajax request.
To convert the image, you have to use the browsers file api:
// Convert file to base64 string
export const fileToBase64 = (filename, filepath) => {
return new Promise(resolve => {
var file = new File([filename], filepath);
var reader = new FileReader();
// Read file content on file loaded event
reader.onload = function(event) {
resolve(event.target.result);
};
// Convert data to base64
reader.readAsDataURL(file);
});
};
// Example call:
fileToBase64("test.pdf", "../files/test.pdf").then(result = {
console.log(result);
// ##### PUT YOUR AJAX CALL HERE
});

How to convert BLOB to image using python

I need to send an image from client to server using blob
I have converted a image to BLOB in jquery (client side) and sending the blob to python flask (server side) the problem is, I can't recreate image from BLOB. I have tried the following code in python but failed to get the image
Jquery code to convert image to blob:
function changeFile() {
var file = this.files[0];
var reader = new FileReader();
reader.addEventListener('load', readFile);
reader.readAsText(file);
}
function readFile(event) {
document.body.textContent = event.target.result;
console.log(event.target.result);
appendFileAndSubmit(event.target.result);
}
function appendFileAndSubmit(imageUrl){
var ImageURL = imageUrl
var data = {
'logo':ImageURL
}
$.ajax({
url: 'http://sdsdss/User/imgBlob',
method: 'POST',
dataType : 'json',
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8'
}).done(function(response){
var datas = JSON.parse(response);
console.log(datas);
});
}
document.getElementById("inp").addEventListener("change", changeFile);
Python Code: To recreate BLOB to image
function getImage(self):
reqData = json.loads(request.data)
Logo = reqData['logo']
png_recovered = base64.decodestring(Logo)
f = open("temp.png", "w")
f.write(png_recovered)
f.close()
Don't read the file as text, You are dealing with binary data. Best way to transfer binary with json is if you read the file as base64 instead reader.readAsDataURL(file) This will encode all bytes to a web safe base64 string (no slash or plus). Then you have to decode it with python as well.
I discourage you from using json when dealing with file transfer as it will increase the bandwidth with ~3 times as much (not to mention the time it also takes to decode and encode it back and forth) For this I recommend you instead use FormData.
var fd = new FormData()
fd.append('logo', files[0])
$.ajax({
url: 'http://sdsdss/User/imgBlob',
method: 'POST',
data: fd,
// Setting false prevent jQuery from transforming the data
processData: false,
contentType: false
}).then(function(response) {
console.log(JSON.parse(response))
})
or simpler yet, just post the file without any formdata, json or extra fields if they are not necessary.
fetch(uploudUrl, { method 'PUT', body: this.files[0] })

How to download and then upload image with AngularJS

I have an Angularjs 1.5.0 web application which should communicate with a REST-based web service that I had developed (using dropwizard & jersey) and tested that it works perfectly.
The REST web service method is like this:
#POST
#Path("/saveImage")
public Response saveImage(
#FormDataParam("imagefile") InputStream uploadedInputStream,
#FormDataParam("imagefile") FormDataContentDisposition fileDetail) {
// save image on server's file system and return OK
}
Scanned images are available to me by the scanner's local web server through a link like this: http://localhost:9980/thumb/random-generated-guid.jpg
In my angularjs code, I want to send the image which is available with the link above to my REST service.
Does anybody know how to do this?
I tried first saving the image as a blob and then send it to the web service. I could save the image using javascript's XMLHttpRequest but sending always fails.
Code for saving the image as Blob:
var xhr = new XMLHttpRequest();
xhr.open('GET', imageAddress, true);
xhr.responseType = 'blob';
var imageData = null;
xhr.onload = function(e) {
if (this.readyState === 4 && this.status === 200) {
// get binary data as a response
imageData = this.response;
var gatewayResponse = sendToGateway(imageData);
}
};
Code for sending the blob data:
var sendToGateway = function(imageDataBlob) {
var formdata = new FormData();
formdata.append('imagefile', imageDataBlob)
$.ajax({
url: 'http://localhost/eval/saveImage',
method: 'POST',
contentType: 'multipart/form-data; charset=UTF-8',
data: formdata,
dataType: 'json',
})
.done(function(response) {
$log.info("**************** response = " + response);
alert("response:\n" + response);
})
.fail(function(jqXHR, textStatus, errorThrown) {
$log.error("!!!! FAIL !!!!!!!!!");
alert("FAIL !!!!!!!");
})
.always(function(){
$rootScope.scannerInactive = false;
doStartPreviewUpdate();
});
};
Actually, the problem is when the sendToGateway(imageData); is called, I get the error:
TypeError: 'append' called on an object that does not implement
interface FormData.
value = jQuery.isFunction( value ) ? value() : ( value == null ? "" :
value );
oops, I found the problem. I should have added the following directives to the $.ajax() call.
processData: false,
contentType: false,

Dropbox direct upload files from browser

I am trying to upload files directly to dropbox [from a browser / web application], The "uploadFile" function on the code API needs the file to be uploaded available on the server, this puts me in trouble, because I do not want any files to be uploaded to my server and from there to dropbox.
$f = fopen("test.jpg", "rb"); // requires file on server
$result = $dbxClient->uploadFile("test.jpg", dbx\WriteMode::add(), $f);
fclose($f);
Tried out this https://github.com/dropbox/dropbox-js disappointed to say that there is no clear documentation, many of the links on the documentation part is broken.
I need the files to be uploaded to my account and the clients need not login to dropbox.
Any pointers would be really appreciated. looking for Ajax / JavaScript methods.
Update
I have tried the following, but no response from Dropbox
HTML
<input type="file" name="file" id="file" onchange="doUpload(event)">
JavaScript
var doUpload = function(event){
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
var arrayBuffer = reader.result;
$.ajax({
url: "https://api-content.dropbox.com/1/files_put/auto/uploads/" + input.files[0].name,
headers: {
Authorization: 'Bearer ' + MyAccessToken,
contentLength: file.size
},
crossDomain: true,
crossOrigin: true,
type: 'PUT',
contentType: input.files[0].type,
data: arrayBuffer,
dataType: 'json',
processData: false,
success : function(result) {
$('#uploadResults').html(result);
}
});
}
reader.readAsArrayBuffer(input.files[0]);
}
Dropbox just posted a blog with instructions on how to do this. You can find it at https://blogs.dropbox.com/developers/2016/03/how-formio-uses-dropbox-as-a-file-backend-for-javascript-apps/ (Full disclosure, I wrote the blog post.)
Here is how to upload a file.
/**
* Two variables should already be set.
* dropboxToken = OAuth token received then signing in with OAuth.
* file = file object selected in the file widget.
*/
var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(evt) {
var percentComplete = parseInt(100.0 * evt.loaded / evt.total);
// Upload in progress. Do something here with the percent complete.
};
xhr.onload = function() {
if (xhr.status === 200) {
var fileInfo = JSON.parse(xhr.response);
// Upload succeeded. Do something here with the file info.
}
else {
var errorMessage = xhr.response || 'Unable to upload file';
// Upload failed. Do something here with the error.
}
};
xhr.open('POST', 'https://content.dropboxapi.com/2/files/upload');
xhr.setRequestHeader('Authorization', 'Bearer ' + dropboxToken);
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.setRequestHeader('Dropbox-API-Arg', JSON.stringify({
path: '/' + file.name,
mode: 'add',
autorename: true,
mute: false
}));
xhr.send(file);
Then to download a file from dropbox do this.
var downloadFile = function(evt, file) {
evt.preventDefault();
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
if (xhr.status === 200) {
var blob = new Blob([xhr.response], {type: ’application/octet-stream’});
FileSaver.saveAs(blob, file.name, true);
}
else {
var errorMessage = xhr.response || 'Unable to download file';
// Upload failed. Do something here with the error.
}
};
xhr.open('POST', 'https://content.dropboxapi.com/2/files/download');
xhr.setRequestHeader('Authorization', 'Bearer ' + dropboxToken);
xhr.setRequestHeader('Dropbox-API-Arg', JSON.stringify({
path: file.path_lower
}));
xhr.send();
}
FileSaver and Blob will not work on older browsers so you could add a workaround to them.
As other answers have noted, each session uploading or downloading the file will need to have access to a dropbox token. Sending someone else's token to a user is a security issue since having the token will give them complete control over the dropbox account. The only way to make this work is to have each person authenticate with Dropbox and get their own token.
At Form.io we've implemented both the authentication and the upload/download into our platform. This makes it really easy to build web apps with dropbox as a backend for files.
"I need the files to be uploaded to my account and the clients need not login to dropbox."
Then you'll really need to do the upload server-side. To do it client side would mean sending the access token to the browser, at which point any user of your app could use that access token to do whatever they wanted with your account. (E.g. delete all the other files, upload their private DVD collection, etc.)
For security reasons, I would strongly recommend doing the upload server-side where you can keep the access token a secret.
The answers given so far don't utilize the Dropbox javascript SDK which I think would prob be the best way to go about it. Check out this link here:
https://github.com/dropbox/dropbox-sdk-js/blob/master/examples/javascript/upload/index.html
which provides an example which is ofc dependent on having downloaded the SDK. (Edit: after playing with SDK I realize that it creates a POST request similar to the accepted answer in this thread. However something the popular answer omits is the presence of an OPTIONS preflight call that the sdk makes prior to the actual POST)
I might also add that something that is not shown in the dropbox sdk examples is that you can upload a blob object to dropbox; this is useful for instance if you want to dynamically extract images from a canvas and upload them and don't want to upload something that has been selected from the file system via the file uploaded input.
Here is a brief example of the scenario I'm describing:
//code below after having included dropbox-sdk-js in your project.
//Dropbox is in scope!
var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
//numerous stack overflow examples on creating a blob from data uri
var blob = dataURIToBlob(canvas.toDataUrl());
//the path here is the path of the file as it will exist on dropbox.
//should be unique or you will get a 4xx error
dbx.filesUpload({path: `unq_filename.png`, contents: blob})
Many thanks to #smarx with his pointers I was able to reach the final solution.
Also I have added a few extra features like listening to upload progress so that the users can be showed with the upload progress percentage.
HTML
<input type="file" name="file" id="file" onchange="doUpload(event)">
JavaScript
var doUpload = function(event){
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
var arrayBuffer = reader.result;
var arrayBufferView = new Uint8Array( arrayBuffer );
var blob = new Blob( [ arrayBufferView ], { type: input.files[0].type } );
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL( blob );
$.ajax({
url: "https://api-content.dropbox.com/1/files_put/auto/YourDirectory/" + input.files[0].name,
headers: {
'Authorization':'Bearer ' +YourToken,
'Content-Length':input.files[0].size
},
crossDomain: true,
crossOrigin: true,
type: 'PUT',
contentType: input.files[0].type,
data: arrayBuffer,
dataType: 'json',
processData: false,
xhr: function()
{
var xhr = new window.XMLHttpRequest();
//Upload progress, litsens to the upload progress
//and get the upload status
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var percentComplete = parseInt( parseFloat(evt.loaded / evt.total) * 100);
//Do something with upload progress
$('#uploadProgress').html(percentComplete);
$('#uploadProgressBar').css('width',percentComplete+'%');
}
}, false);
},
beforeSend: function(){
// Things you do before sending the file
// like showing the loader GIF
},
success : function(result) {
// Display the results from dropbox after upload
// Other stuff on complete
},
});
}
reader.readAsArrayBuffer(input.files[0]);
}
U have used the PUT method as our only objective is to upload files,As per my studies on various resources ( StackOverflow and zacharyvoase ) A put method can stream large files, also its desigend to put files on a specified URI , if file exist the file must be replaced. A PUT method cannot be moved to a different URL other than the URL Specified.
The Risk
You are at risk by using access token at client side, there needs to be high security measures to mask the token. But modern Web dev tools like Browser consoles , Firebug etc can monitor your server requests and can see your access token.
upload.html
Upload
upload.js
$('#form_wizard_1 .button-submit').click(function () {
var ACCESS_TOKEN ="Your token get from dropbox";
var dbx = new Dropbox({ accessToken: ACCESS_TOKEN });
var fileInput = document.getElementById('files1');
var file = fileInput.files[0];
res=dbx.filesUpload({path: '/' + file.name, contents: file})
.then(function(response) {
var results = document.getElementById('results');
results.appendChild(document.createTextNode('File uploaded!'));
res=response;
console.log(response);
})
.catch(function(error) {
console.error(error);
});
}

Download pdf file in response to post request

I want a server-side report to be generated from a javascript object and returned as a PDF. In one request.
I've tried a windows.location.href with the object in the query string, but the query string gets too long.
I've also tried a jQuery post with the object as attachment like this:
$.ajax({
url: "/SalesCalls/SalesCallReport/GetReport",
data: JSON.stringify(unmappedItem),
timeout: 10000,
type: 'POST',
contentType: 'application/json',
success: function (response, status, request) {
var disp = request.getResponseHeader('Content-Disposition');
if (disp && disp.search('attachment') != -1) {
var type = request.getResponseHeader('Content-Type');
var blob = new Blob([response], { type: type });
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
window.location = downloadUrl;
}
}
});
I stole the code in the success callback from another post on stackoverflow. It transfers the object to the server alright, but the output somehow doesn't work, I just get a blank pdf. I can see response contains the binary pdf, so I'm somehow missing a step.
The fact that this runs only on modern browsers is no problem.

Categories