blueimp / jQuery-File-Upload

File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.
https://blueimp.github.io/jQuery-File-Upload/
MIT License
30.95k stars 7.95k forks source link

Android (default browser) sends Blobs as empty files (e.g. using Chunked Uploads) #1947

Open cbepxpa3ym opened 11 years ago

cbepxpa3ym commented 11 years ago

Do not work. Gives error: File is too small

blueimp commented 11 years ago

Android only supports XHR style uploads from version 3.2+ onwards, but not chunked uploads: https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support

cbepxpa3ym commented 11 years ago

I understand, but in this case the script should use non-chunked upload automaticaly.

P. S. No need to post the links from your documentation. I read it already few times. Count me as your bug-tester :) So, I am not asking you to add ability for chunked upload, I am just telling you it fails, instead of use a non-chunked upload.

blueimp commented 11 years ago

Yeah, that's why I reopened this issue. However, this might be tricky, as the Android browser passes all checks for chunked uploads, but doesn't properly implement it, it seems.

Thanks for bug testing anyway! :)

blueimp commented 11 years ago

OK, I had a look into this issue and unfortunately this is a bug in the Blob API implementation of Android. The worst news is that there is no feature detection possible to detect this bug, before making the actual request.

Here are the related issues on the Android issues tracker: http://code.google.com/p/android/issues/detail?id=22441 http://code.google.com/p/android/issues/detail?id=36524

Please star those issues and add your voice so this problem will get fixed by the Android developers.

cbepxpa3ym commented 11 years ago

What about a temporary hardcoded check of platform and browser to disable Chunked Uploads?

blueimp commented 11 years ago

Since chunked uploads are not enabled by default, I would rather suggest, you enable it with a condition, like this:

$('#fileupload').fileupload('option', 'maxChunkSize', !navigator.userAgent.match(/Android/i) && 200000);
cbepxpa3ym commented 11 years ago

Btw, the one reason I would use chunked upload is to avoid php.ini max upload size error. So, I have 120M as a limit in my php.ini, but I can upload let's say a movie of 1.4 GB with chunked upload (I set to a bit smaller value than max upload size limit). I calculate it automatically with your function get_config_bytes, where I changed 1024 into 1000 to get smaller results. So, it returns 120 000 000 instead of 125 829 120 (5 MB less). So, in this case I will never get an empty $_FILES array (with browsers which are compatible with chunked upload of course).

Hampei commented 11 years ago

I explicitly disabled chunked uploads for all browsers both passing the options directly as setting the option after, but am still getting empty files on the server when uploading from android 4.0.4 browser. $('.add_file_btn input').fileupload('option', 'maxChunkSize', false);

File 'Blob5...' is no image, 'application/x-empty' detected.

blueimp commented 11 years ago

Can you reproduce this issue on the demo?

Hampei commented 11 years ago

Yes. The demo says Blob.... 0.00KB file is too small.

It looks like it's trying too upload chunked anyway. On the server side I get things like: [name] => Blob2165f4008f714f1f94e734973277a1da [type] => application/x-empty [tmp_name] => /tmp/phpa5FRB6 [error] => 0 [size] => 0 [options] => Array

That the request is saying the file is 0 bytes seems to be a known problem for chunked uploads. But the file is actually being uploaded if look at the time it takes to finish the request.

blueimp commented 11 years ago

OK, the demo does make use of client-side image resizing, which also creates Blobs, which are also incorrectly handled by Android. So if this issue is the same as on your setup, if you want to support Android, you'll have to disable both chunked uploads as well as client-side image resizing or any other method that doesn't transfer the original File objects.

Hampei commented 11 years ago

Thank you. I was resizing the image client side. disabling that it now works.

albanx commented 11 years ago

Is there any possibility to send the file chunk as base64 encoded string, since android browser can handle readAsUrlData? By the way the chrome android version does not have this bug.

blueimp commented 11 years ago

Since both Opera 12 and the default Android browser (but not Chrome on Android) suffer from this bug, which unfortunately cannot be feature tested without involving an actual request to the server, I recommend the following check before enabling chunked uploads or client-side image resizing:

var supportsBlobXHR = !/Android(?!.*Chrome)|Opera/.test(window.navigator && navigator.userAgent)
valencet commented 10 years ago

Hi Blueimp, I am just starting in learning java programming, for my school assignment purpose, I am using your upload plugin in my school project. However, I meet the same issues as above. Client-side image resizing is very important to my project, I can't disable it for some purpose. After study on the issues some time, as your mentioned, image resizing is function well in android default browser, the roof cause should be on the sending blob with xhr. In my studying on this, I have found some useful information from the link in below,

From the link, I come out two idea, 1) Convert the blob to arraybuffer before send with xhr. This is work with a simple testing in http://ghinda.net/jpeg-blob-ajax-android/.

2) Combine the programming concept of file upload from https://github.com/joelvardy/javascript-image-upload to the plugin, since they are worked in android default browser.

I have study on the java code in your plugin, but I don't how to modify it with potential solution in above for testing, thus, I really need your help for it for me to implement them in my project.

Sorry about that my english is poor because english not my language. Hope to get your response as soon as possible.

blueimp commented 10 years ago

Thanks for your comment, @valencet.

The ArrayBuffer workaround explained here is indeed new to me and valuable information.

Unfortunately the transformation from a Blob to an ArrayBuffer is an asynchronous operation, else we could simply adjust the _initXHRData method, which sets up the XHR data to sent to the server (either the File or Blob as is, or wrapped in a FormData object).

As it is now, the code depending on the _initXHRData method expects a synchronous response. Although it's certainly possible to change that, it would require a significant refactoring of the core code base.

DarrenInwood commented 10 years ago

Added a pull request with a fix for this: https://github.com/blueimp/jQuery-File-Upload/pull/3052

rdetert commented 10 years ago

@DarrenInwood Have you been using your fork in production at all? I'm debating how to approach this issue. I'm leaning towards rolling my own base64 method.

DarrenInwood commented 10 years ago

@rdetert Yes we've been using this in production, it works fine. :-)

chandon commented 10 years ago

@DarrenInwood Does your fork works with the ImageResize option ? I've tested it, and it doesn't seem to work...