I want to upload a (single) file to a server and show the progress of the upload.
I know I can upload a file using HTTP POST. I'm not familiar with web-sockets, but as I understand, binary data can also be sent that way and because web sockets are bi-directional I could get the progress of the upload.
I'm not worried about older browsers so iframe's and flash solutions aren't very appealing unless there is a significant advantage in going that route.
I'm also curious as to the best server-side technology. Are their advantages to using a WSGI server like Django? Or maybe non-blocking I/O technology like Node.js? I'm not asking if web framework x is better than web framework y, or server x is better than server y. But simply what the ideal technology should have in order to facility uploads in the client.
Update: It seems like the server side does not have bearing on the technologies/API's available on the client to facilitate uploads.
Edit (2017-10-17): As of now, there is also the option to use Fetch API. It offers essentially the same capabilities as XMLHttpRequest behind a more modern promise-based API. There is a polyfill for browsers that don't support window.fetch()
natively (which is mainly Internet Explorer and older Safari versions right now).
Clearly XMLHttpRequest. Its capabilities in modern browsers are enormous and cover almost all scenarios. It will produce a standard POST or PUT request, any web server and framework combination can deal with that.
While web sockets are nice for some scenarios, it's a different protocol that adds lots of complexity - they are only worth using if you need real-time responses from the server. And as you noted yourself, other approaches like Flash are merely ugly hacks.
Normally, you won't have direct access to files. So you will have an <input type="file">
form field somewhere on your page and wait for the user to choose a file. The options then are:
request.send(input.files[0])
. The request body will be the file's contents and nothing else, no encoding will be performed and no metadata like file name will be transmitted. Browser compatibility: Chrome 7, Firefox 3.6, Opera 12, IE 10.request.send(new FormData(input.form))
. Here the form contents will be encoded as multipart/form-data
, meaning that you can send multiple form fields and metadata like field and file names will be transmitted as well. You can also modify the FormData
object before sending it. Depending on the server-side framework, handling this request might be simpler than raw data, there are typically many helpers you can use. Browser compatibility: Chrome 6, Firefox 4, Opera 12, IE 10.You can listen to progress
events on XMLHttpRequest.upload
. The progress
events have loaded
and total
properties that allow determining how far you've got with your request. Browser compatibility: Chrome 7, Firefox 3.5, Opera 11.60, IE 10.
There are of course existing libraries wrapping the functionality outlined here. These are mentioned in other answers, searching on the web will certainly turn up even more. I explicitly don't want to propose any libraries here - which of them if any you should use is purely a matter of preference.