How to send big files using ajax? - javascript

So currently I'm working on a simple project where users gets to upload an image to server. Before I mention my problem here is how I'm doing it:
Client:
var dataURL = sendingcanvas.toDataURL("image/*");
var imagedatatosend = dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
formdata = {
'image': imagedatatosend
};
$.ajax({
url: '../receive',
type: 'POST',
data: formdata,
encode: false,
success: function(result){
alert(result);
}
});
FYI: imagedatatosend size is lower than 5MB and contains exactly the file data selected.
Basically What happens Is that users select an image using <input type="file" tag Then I'm setting that selected file drawn in a canvas to convert it to base64 and send it to server.
Java Server:
String datareceived = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
byte[] bImg = Base64.decodeBase64(datareceived.getBytes("UTF-8"));
FileOutputStream fos = new FileOutputStream("hi.jpg");
fos.write(bImg);
fos.close();
I think I might not need to explain what the code above does. But I'm facing some serious performance problem I mean It takes some huge time to write the data to hi.jpg file, even if I try System.out.println(datareceived); It takes seconds for my mouse click to respond on server console.
I don't know why is it happening, Do I need to send the image data as multipart or what?
All replies are appreciated and Thanks in Advance:)

Use XMLHttpRequest and FormData to append the file. It will be sent using multipart and chunked appropriately.
See: https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects

Related

JQuery ajax POST with FormData doesn't send any values

There seem to be lots of posts about this, but can't find a solution amongst them and I've hit a brick wall. Help, dear Stackers!
I'm writing a bit of code that lets users choose a profile picture, crop it and then save the cropped image on the server. I'm using the Cropper.js library to handle the actual cropping and have established that's working because I can display the crop live with this code:
var imageData = cropper.getCroppedCanvas().toDataURL();
var profileimage = document.getElementById('myProfilePhoto');
profileimage.src = imageData;
Now I want to send the cropped image to the server, and the best method would appear to be create a blob and Ajax that over to a php script to handle it.
cropper.getCroppedCanvas().toBlob(function (blob) {
var formData = new FormData();
formData.append('file', blob);
formData.append('uuid', '{a unique identifier}');
$.ajax({
type: 'POST',
url: '{the php script}',
data: formData,
processData: false,
contentType: false,
success: function (response) {
console.log('Upload success: '+response);
},
error: function () {
console.log('Upload error');
}
});
});
And at this stage I'm just getting my php script to var_dump($_REQUEST) so I can see in the console what the script thinks it's getting. However, the response is just sending back the default $_REQUEST objects like PHPSESSID and no file or uuid input.
What am I doing wrong?
Thanks in advance for any pointers.
If you are sending via post in order to see the request put this code
var formData = new FormData();
formData.append('file', blob);
formData.append('uuid', '{a unique identifier}');
formData.append('_method', 'PATCH'); <---add this and you're good to go
So the answer was annoyingly simple but frustratingly hard to find.
My server had an .htaccess rewrite rule which automatically changed www. addresses to the non-www version, and obviously I'd been dumb enough to include the www. in the URL I was calling, and it seems that's enough to strip off the $_POST data in these circumstances.
So FormData() and blobs are all red herrings here - it's just a redirect that's the cause.

Unable to send base64 video through Ajax Post to PHP

When I try to upload a MP4 video with 16.9 MB size, using ajax async post to an PHP file the console triggers an error saying: POST http://website.com/proc_vids.php net::ERR_EMPTY_RESPONSE
I know for a fact that this problem is related with PHP memory_limit because when I set to 200 MB it's all fine but when I change it back to 100 MB this error happens.
I can't even get the POST to an PHP variable because as soon as the ajax post call is made it triggers the error without even doing anything on server side (PHP). Here is the ajax post code:
var proc = 1;
video = document.getElementById('preview_video').src;
$.ajax({
'async': true,
'type': "POST",
'global': false,
'dataType': 'json',
'url': "proc_vids.php",
'data': {proc: proc, video: video}
}).done(function () {
//Do something
});
PHP code:
$proc = $_POST['proc'];
if ($proc == 1){
//$video = $_POST['video'];
}
As you can see I commented the line where I pass the POST to a variable and still triggering the error.
What can I do to the video variable containing the base64 code to not expand consuming such high memory levels?
Is there any alternatives without setting the memory_limit higher?
Problem solved thanks to cmorrissey!
I used the same method as described in this thread: Convert HTML5 Canvas into File to be uploaded?
Sending AJAX POST as a FormData and converting the base64 data to Uint8Array into a blob is the key to not allocate PHP memory when the POST is made. But be careful tho because older browsers may not support blob.
Thank you guys ;)

How do I send image canvas data to Transloadit?

Transloadit appears to have only a Upload Form API. I wish to send the contents of my canvas to Transloadit like so:
data = canvas.toDataURL();
// POST this data to Transloadit
$.ajax({
type: 'POST',
url: 'http://api2.transloadit.com/assemblies',
// what goes here?
}).done(function() {
console.log('Done uploading!');
});
Is this possible?
It appears that Transloadit still does not support base64 data, but with newer browsers it's possible to take base64 data from a variable, convert it to binary, and send it in a file upload.
http://support.transloadit.com/discussions/questions/8587-how-to-upload-a-canvas-image-to-transloadit

Multipart or base64 for AJAX file uploads?

I'm writing a single page application with EmberJS and need to upload a few files.
I wrote a special view, that wraps the file input field and extracts the first file selected. This lets me bind the File-Object to a model-attribute.
Now I have to choose.
I can write a special file transform, that serialises the File-Object to base64 and simply PUT/POST this.
Or I can intercept the RESTAdapter methods createRecord and updateRecord to check every model for File-Objects and switch the PUT/POST requests to multipart/form-data and send it with the help of FormData
Does one of these directions pose significant problems?
I've had to evaluate the same concern for a Restful API I'm developing. In my opinion, the most ideal method would be to just use the RESTAdapter with base64 encoded data.
That being said, I had to use the multipart/form-data method in my case, because the data transfer is 30% higher when you base64 encode the file data. Since my API would be have to accept large (100MB+) files, I opted to have the POST method of the API to receive multipart form data, with the file and json data being one of the POST variables.
So, unless you need to upload large files like in my case, I'd recommend always sticking to the REST methods.
Just ran into this myself, and ended up using a simple jQuery AJAX call using the FormData object. My multi-select implementation (where one can drop multiple files at once) looks like this:
filesDidChange: function() {
// Get FileList
var $input = this.$('input'),
fileList = $input.get(0).files;
// Iterate files
for (var i = 0; i < fileList.length; i++) {
var file = fileList[i],
formData = new FormData();
// Append information to FormData instance
formData.append('attachment[title]', file.name);
formData.append('attachment[file]', file);
formData.append('attachment[post_id]', this.get('post.id'));
// Send upload request
Ember.$.ajax({
method: 'POST',
url: '/attachments',
cache: false,
contentType: false,
processData: false,
data: formData,
success: makeSuccessHandler(this),
error: makeErrorHandler(this)
});
}
// Notify
this.container.lookup('util:notification').notify('Uploading file, please wait...');
// Clear FileList
$input.val(null);
},

How to build a file from binary string using javascript

I am trying to use BusinessObject RESTful API to download a generated (pdf or xls) document.
I am using the following request:
$.ajax({
url: server + "/biprws/raylight/v1/documents/" + documentId,
type: "GET",
contentType: "application/xml",
dataType: "text",
headers: {"X-SAP-LogonToken": token, "Accept": "application/pdf" },
success: function(mypdf) {
// some content to execute
}
});
I receive this data as a response:
%PDF-1.7
%äãÏÒ
5 0 obj
<</Length 6 0 R/Filter/FlateDecode>>
//data
//data
//data
%%EOF
I first assumed that it was a base64 content, so in order to allow the users to download the file, I added these lines in the success function:
var uriContent = "data:application/pdf; base64," + encodeURIComponent(mypdf);
var newWindow=window.open(uriContent, 'generated');
But all I have is an ERR_INVALID_URL, or a failure while opening the generated file when I remove "base64" from the uriContent.
Does anyone have any idea how I could use data response? I went here but it wasn't helful.
Thank you!
. bjorge .
Nothing much can be done from client-side i.e. JavaScript.
The server side coding has to be changed so that a url link is generated (pointing to the pdf file) and sent as part of the response. The user can download the pdf from the url link.
You cannot create file using javascript, JavaScript doesn't have access to writing files as this would be a huge security risk to say the least.
To achieve your functionality, you can implement click event which target to your required file and it will ask about save that file to user.

Categories