⬆️ ⬇️

Uploading files using HTML5 and how many times we said bad words

The task was to find or create a file uploader on a server that uses the capabilities of HTML5 for multiloading. The loader should:



It is precisely because of the lack of experience with flash, that only JavaScript was chosen to create the bootloader.



So what came of it




First there was a search: SWFupload, Uploadify and others were studied. Perhaps not too well, but each of them did not meet all the requirements.



Bugs, bugs, bugs. Some versions of Flash cannot control the variable name. SWFupload does not send cookies, but it does have a cookie collector, and it sends them only with GET or POST methods. However, we have a CMS on the server that checks the user's session precisely on the basis of cookies, so Flash was discarded and a solution was selected using HTML5.

Since FileApi is only supported by FF 3.0+, Chrome and Safari 4+, we’ll analyze the intricacies of working with these browsers.

')

Subtlety number 1



Getting the contents of a file in Chrome using readAsBinaryString.

When using this method, we are faced with an incomprehensible problem that all files come beaten, the size of which is about 1.5 times the original size. We didn’t manage to overcome this problem, so for chrome (as well as safari) we used FormData.



To send a group of files + some data using the POST method in FF (up to 4.0), we create a multipart / form-data:

Content-Type: multipart/form-data; boundary=------multipartformboundary1295790618

\r\n

--------multipartformboundary1295790618

\r\n

Content-Disposition: form-data; name='user_files[]';filename='My_File1.jpg'

\r\n

Content-Type: application/octet-stream

\r\n

\r\n



\r\n

--------multipartformboundary1295790618

\r\n

Content-Disposition: form-data; name='user_files[]';filename='My_File2.jpg'

\r\n

Content-Type: application/octet-stream

\r\n

\r\n



\r\n

--------multipartformboundary1295790618

\r\n

Content-Disposition: form-data; name='my_param'

\r\n

\r\n

Param_value

\r\n

--------multipartformboundary1295790618

\r\n

Content-Disposition: form-data; name='my_param'

\r\n

\r\n

Param_value

\r\n

--------multipartformboundary1295790618--

\r\n




Subtlety number 2



The definition of FormData support can be checked as follows:

function isFormDataSupported() {

return (window.FormData);

}





Subtlety number 3



FF 3.0 / 3.5 and FF 3.6 use different functions to get the contents of the files:

FF 3.0 / 3.5: readAsBinary ()

FF 3.6: getAsBinary ()



Subtlety number 4



There is also a difference in sending files via XMLHttpRequest:

for FormData, you need to send using the send () method, and to send files received by the getAsBinary () method or using readAsBinaryString, you must send with the sendAsBinary () method.



Subtlety number 5



FF rarely triggers the progress event of XMLHttpRequest, as opposed to chrome or Safari. In fact, at FF, the progress event sometimes did not work at all with very fast connection or on localhost.



Subtlety number 6



At the abort event, the XMLHttpRequest in FF also triggers the error event. With this you need to be especially careful if you have a handler for errors there - this may cause additional questions to the user.



Subtlety number 7



For PHP, I advise you to pay attention to the following settings in php.ini:



post_max_size is the maximum size of POST.

upload_max_filesize - maximum file size.

max_file_uploads - the maximum number of downloaded files.



If you use our script, do not forget to change the script for your server settings.



Demo for uploading images (worth filter by extensions)

Download demo

Good presentation on AJAX downloads



UPDATE:



Subtlety number 8 (thanks to soltpain for noticing this bug)



In Windows, there is another caveat in choosing a set of files through [input type = file multiple]:

The number of files available for selection depends on the total length of the names of the selected files. For chromium - 256 characters, for FF - 4096 (the length is not a single file, but the total length of the names, that is, if there are files whose name consists of 20 characters, then in chrome you can select a maximum of 10 files). In Linux, everything is fine.



Bug description:

codereview.chromium.org/4198004

Source: https://habr.com/ru/post/112538/



All Articles