PHP + Ajax: Uploading large content via Ajax (413 HTTP Code) - php

I've spent good 2 days on this issue and I'm reaching a desperation point. I am hitting my request limits when I am uploading file content via Ajax - Request Entity Too large. I am on an Apache server. I am able to modify php.ini and htaccess but not able to modify any configs beyond this as I do not have access to those.
Problem:
I have a base64 encoded content of an image that I need to upload to my server (roughly 1MB in size). I have tried uploading this value, which results in 413 error code. As an experiment, I've tried uploading an image using a <input type='file' /> field which works for images and files much bigger than 1MB. It seems I am hitting the 413 error only if I have data >1MB present in the request params (eg adding data in an input field, or adding base64 representation of an image into one of the request params). Uploading the same file using File input works fine though.
The real issue is that in my website I can't have users upload image via File Input field. I only have the base64 content of the image that needs to be uploaded. Given that I can't modify my server settings, is there a way I can upload this content into my server??
Additional Info:
I am using JS FormData() object. The content of my form goes into this object and gets uploaded to my server. I can dynamically add values to this object using methods like formdata.append().
If I append large base64 string from above description, I hit a 413 error.
If I add a text field into the form and copy/paste the base64 string into the input field, I also hit the 413 error
If I upload the same image from my machine using <input type='file' /> field and upload the FormData object the image comes through fine.
Hope this is enough info. As a bonus - if anyone can explain why uploading the file via File Input works, but uploading the same data via a text field doesn't that would be quite beneficial also!

For anyone having similar problems in the future, I've found the answer in one of the answers to this question
Essentially we'll add the base64 string as a blob to the formData object using:
var formData = new FormData();
var blob = new Blob(['Lorem ipsum'], { type: 'plain/text' });
formData.append('file', blob,'readme.txt');
This seems to mimic the behaviour of File Input.

Related

What is the best way to send image file to server: as base64 or image file?

I have an app with REST on AngularJS/PHP(Yii);
I'm not good in backend.
I'm interesting what is the best way to upload a picture to server.
I'm using Angular Material directive and get image in base64 format.
Should I post image as base64?
Or it's better to convert it and what format?
Or maybe (It's not my opinion) to upload it from html form directly
to backend using Yii?
I think you trying to upload an image file from restangular,
Try the following code:
function upload($scope.image) {
var formData = new FormData();
formData.append($scope.image);
Restangular.one('/* your url*/').withHttpConfig({transformRequest:angular.identity})
.customPOST(formData, '', undefined, {'Content-Type': undefined}) }
by setting the content type undefined browser will automatically detect file type
that will handle your UI side. I have less idea about yii framework, but in following you can get the image file by using following type:
java : #ResponseBy : multipart/form-data,
php : $_file
I think its better to upload file using form-data.
If you plan to display those uploaded images on a website or mobile application, you can use ImageKit.io. Easy API to upload and you get an URL for displaying that image. It will take care of optimization and also provides URL-based parameters for resizing, cropping etc.
If you have a base64 data url representation of the file as you are saying, then you can convert that into a file Blob, add a name to it and upload the Blob as data file.

Laravel 5.1 returning error 301 on AngularJS post containing base64 encoded image

Help, because I'm losing my mind.
I built an API using Laravel 5.1, and my app uses AngularJS (1.4.5) that communicates with the API. FabricJS plugin creates a Base64 encoded image from a canvas, and I want to send it using AJAX post method to a Laravel post route.
My post data in Javascript looks something like this:
var postData = {
image: "data:image/png;base64,iVBORw0KGgoAAAA(...)",
data: (some arrays and objects)
Now, when I post the data, it's about 2 MB with the image data. On post to Laravel route (post route, no trailing slashes), Laravel returns a 301 Moved Permanently (in Firefox 40.0.2), and in Google Chrome, Network tab displays 301 error followed by error 405 Method Not Allowed with an error in Laravel's RouteCollection.php on line 201.
Post JSON is valid (checked), and post works fine when I don't post the image data (parameter is set to image: null).
Server PHP version is 5.6.12.
Error seemingly gets output when I upload large JPEG files (like, compression 100 or 98). PHP settings says my upload limit is 20MB.
On the other hand, that same post works when the image is a JPEG, full HD, saved from Photoshop with Save for Web..., compression 80 with progressive option enabled.
WORKAROUND
Colleague and I tried this and it worked for us: for some reason, Laravel doesn't like full image data as a string, example:
data:image/png;base64,iVBORw0KGgoAAAA(...)
Solution is to break down that to actual base64 encoded string (in this case iVBORw0KGgoAAAA(...)) and from first part, and pass the file type as another parameter.
So the Javascript object (from top of post) would be something like this:
var postData = {
image: "iVBORw0KGgoAAAA(...)",
imageType: "png",
data: (some arrays and objects)
Using PHP, we reassemble the entire image string (if "png" prepend "data:image/png;base64," to image) and (in our case) use Intervention Image plugin and save image to a directory on a server.
I had an issue passing sterilized XML.
Try passing the string in a query string and then str_replace(' ', '+', $base64string);

How to paste image in chrome, then upload it to a server with PHP

I actually want to upload an image to a server.
To achieve this, i want the user just paste the image into chrome (the image is a print screen in fact), and then i post the stream to a php page, convert the stream as an image, and then upload it.
How can i achieve this web application ?
Today i have develop some differents parts :
I used this script, and i create the Upload.php page which gets the post variable and try to Create and image.
The problem i have, is that when i post the data, i only get a blob. I would like to get a base64 stream.
Can you help me ?
Thanks in advance.
I'm not sure why you are specifically looking for a "base 64 stream". If you are sending the Blob to your server via ajax, as far as your server is concerned, it's a file. Treat it no different than any other upload server-side. A Blob is a File without a name property. That's perhaps a bit overly-simplistic, but my point is that, again, this is really nothing more than a file as far as your server knows.
Assuming you are sending a multipart-encoded request, I'd like to point out that most user agents will set the filename property of the item's Content-Disposition header in the request to "blob" when the item you are uploading is a Blob instead of a file. It is possible to change this value in some browsers via the 3rd argument in FormData's append method, but I wouldn't rely on this just yet.
Also note that, if you are interested in a library that handles all of this already, I maintain, Fine Uploader which natively supports uploading images via paste in Chrome.
To answer this old question: Posting an image from clipboard with chrome is pretty much the same as posting a dropped file - except that the image/blob doesn't have the properties "name" and "lastModified".
var entry = items[i].webkitGetAsEntry();
if (!entry) entry = items[i].getAsFile();
if (entry instanceof Blob) /** CHROME pastet Bilder als Blob **/
{
entry.isFile = true;
entry.lastModifiedDate = new Date();
entry.name = ""+new Date().getTime()+"."+entry.type.split('/')[1];
}
if (entry.isFile)
{
//handle dropped file
}

base64 encoded image isn't being sent by POST

I have a couple of image drop places made with html5. When the image is parsed and converted to data (and encoded in base64), I grab that data and send via post to a php file.
On localhost, that base64 string is received perfectly in the php file. However, when I move to a server, both image preprocessing and base64 sending to the server work (I read the headers), but when in the php file, that base64 string is no longer there. Is there anything I am missing?
Some extra information:
I don't url encode the string, because without doing so it worked locally, and doing that the server still doesn't get the base64 data.
I haven't topped the post_max_size (8M in my case, yet the base64 string plus the other data weights about 50kb)
Breaking news
I tried to upload 600kb of data. Now the server prompts this:
<html><head>
<title>413 Request Entity Too Large</title>
</head><body>
<h1>Request Entity Too Large</h1>
The requested resource<br />/altmail/admin/calls/ajax.previewnewsletter.php<br />
does not allow request data with POST requests, or the amount of data provided in
the request exceeds the capacity limit.
</body></html>
Again, post_max_size is big enough.
Breaking news 2
After uploading the opposite, a 38x38, 220bytes picture, it uploaded correctly.
Check the Apache Request size limits:
http://httpd.apache.org/docs/2.2/mod/core.html#LimitRequestFieldSize
There is a limit in the size of everything where it comes to HTTP, so if something works here and not there, increase the sizes there. ;)
You're saving the base64 data into a file? If so maybe the folder is not marked for "WRITE", check that.
You are using $_POST or is using global variables in Localhost.
If you are using Global change to $_POST.
If you are using RAW, use the variable like this:
$_GLOBALS['HTTP_RAW_POST_DATA']

Problem with Flash PHP upload

I am using a script to upload photo (written by my own) which allow user to select more than 1 files, using Flash.
When user click upload, as3 will post the upload file to upload.php, resize it, and save it one by one.
The problem:
In production server, if I am uploading many photos and the photos size are very large, >2MB, the uploading progress just stuck in halfway, only the first few photos successfully uploaded.
What I have found out:
If I tried with smaller size photos, or if I disabled the resizing script in upload.php, there are no problem at all.Furthermore, the script work fine in my localhost with newer processor compared to the problematic server with older model)
The resize script is simple. It just check whether the image resolution is large, and use imagecopyresampled() to resize the image if needed.
I tried to unset image resource in upload.php to free up memory but it doesn't help.
What else could be the problem?
If I remember right, there is a 2mb upload limit in php, you can change it in the php.ini file.
I solved the problem.
It happens when I use code like this in AS3:
for(var i:Number = 0; i< fileList.length; i++) {
fileList[i].upload(new URLRequest(param.uploadURL+"&sessionid="+param.session_id));
}
The code seems like pushing upload.php script in very tedious way.
I made changes to both my AS3 and JS, so that JS call to AS3 upload() function only everytime a file upload is completed (from event listener EVENT.COMPLETE)
By making so, AS3 wont call for upload.php synchronously for multiple files. Instead, it wait for a file completed the upload, then call for another upload for the next file.

Categories