This is the first in a two part series about native browser based multifile drag and drop uploads.
Last year when I was working on zugunroute.com I needed to make uploading multiple files from GPS receivers easy. I was delighted to find out that multifile uploads with drag and drop are well supported in modern browsers. Support in the major browsers is there. Firefox, Chrome, Safari, Opera and IE 10 onward all support the posting of multiple files via HTTP.
I’ll start with a brief explanation of how single file uploads work. From there we’ll show how to modify your html and server side code for multiple file uploads. Finally, in part II, we’ll cover the client side approach to handling drag and drop events to invoke the upload.
Single File Uploads
We’ll begin with a short overview of how file uploads work. In traditional circumstances a form has an encoding type of ‘multipart/form-data’ and a file input field of type=’file’.
<form enctype="multipart/form-data" method="POST">
<input multiple="" name="pic" type="file">
<input name="Upload" type="Submit">
</form>
When this form is posted to the server, a portion of the request payload is delineated by a part boundary which is specified as a part of the Content-Type header like so
Content-Type:multipart/form-data; boundary=----WebKitFormBoundary3qPJgaXWpNZgWjeJ
This specifies that “parts” of this POST request are separated by the boundary string.
------WebKitFormBoundary3qPJgaXWpNZgWjeJ
Content-Disposition: form-data; name="pic"; filename="photo-5.JPG"
Content-Type: image/jpeg
------WebKitFormBoundary3qPJgaXWpNZgWjeJ
Content-Disposition: form-data; name="Upload"
Submit
------WebKitFormBoundary3qPJgaXWpNZgWjeJ--
Note the encoded contents of photo-5.JPG are omitted. Various programming environments make the ‘pic’ form data available in their own ways. We were using the sinatra framework to prepare this. We accessed the image data like so:
params[:pic][:filename]
Multifile uploads
By adding the multiple attribute to the file input field, the browser will allow the user to select multiple files. Each file will have be posted to the server encoded in its own part of the http POST request.
<form enctype="multipart/form-data" method="POST">
<input multiple="" name="pic[]" type="file">
<input name="Upload" type="Submit">
</form>
Each file has its own part in the http POST request. Sinatra nice enough to turn the pic parameter into an array of files based on our naming the input field ‘pic[]’ rather than ‘pic’.
------WebKitFormBoundaryBp1xyMflIq8B9Imw
Content-Disposition: form-data; name="pic[]"; filename="photo-2.JPG"
Content-Type: image/jpeg
------WebKitFormBoundaryBp1xyMflIq8B9Imw
Content-Disposition: form-data; name="pic[]"; filename="photo-1.JPG"
Content-Type: image/jpeg
------WebKitFormBoundaryBp1xyMflIq8B9Imw
Content-Disposition: form-data; name="Upload"
Submit
------WebKitFormBoundaryBp1xyMflIq8B9Imw--
In ruby/ sinatra the params[:pic]
variable is now an array of files rather than a single file.