Je souhaite télécharger un (seul) fichier sur un serveur et afficher la progression du téléchargement.
Je sais que je peux télécharger un fichier en utilisant HTTP POST. Je ne suis pas familier avec les sockets Web, mais si je comprends bien, les données binaires peuvent également être envoyées de cette façon et parce que les sockets Web sont bidirectionnelles, je pourrais obtenir la progression du téléchargement.
Je ne m'inquiète pas des navigateurs plus anciens, donc les solutions iframe et flash ne sont pas très attrayantes à moins qu'il y ait un avantage significatif à suivre cette voie.
Je suis également curieux de savoir quelle est la meilleure technologie côté serveur. Leurs avantages sont-ils d'utiliser un serveur WSGI comme Django? Ou peut-être une technologie d'E/S non bloquante comme Node.js? Je ne demande pas si le framework web x est meilleur que le framework web y, ou si le serveur x est meilleur que le serveur y. Mais simplement ce que la technologie idéale devrait avoir pour faciliter les téléchargements chez le client.
Mise à jour: Il semble que le côté serveur n'ait pas d'incidence sur les technologies/API disponibles sur le client pour faciliter les téléchargements.
Edit (2017-10-17): À partir de maintenant, il y a aussi la possibilité d'utiliser Fetch API . Il offre essentiellement les mêmes capacités que XMLHttpRequest derrière une API basée sur les promesses plus moderne. Il existe un polyfill pour les navigateurs qui ne prennent pas en charge window.fetch()
nativement (qui est principalement Internet Explorer et les anciennes versions de Safari en ce moment).
Clairement XMLHttpRequest . Ses capacités dans les navigateurs modernes sont énormes et couvrent presque tous les scénarios. Il produira une POST ou PUT standard, n'importe quelle combinaison de serveur Web et de framework peut gérer cela.
Bien que les sockets Web soient agréables pour certains scénarios, il s'agit d'un protocole différent qui ajoute beaucoup de complexité - ils ne valent la peine d'être utilisés que si vous avez besoin de réponses en temps réel du serveur. Et comme vous l'avez remarqué vous-même, d'autres approches comme Flash ne sont que de vilains hacks.
Normalement, vous n'aurez pas d'accès direct aux fichiers. Vous aurez donc un champ de formulaire <input type="file">
Quelque part sur votre page et attendez que l'utilisateur choisisse un fichier. Les options sont alors:
request.send(input.files[0])
. Le corps de la demande sera le contenu du fichier et rien d'autre, aucun encodage ne sera effectué et aucune métadonnée comme le nom de fichier ne sera transmise. Compatibilité du navigateur : Chrome 7, Firefox 3.6, Opera 12, IE 10.request.send(new FormData(input.form))
. Ici, le contenu du formulaire sera codé comme multipart/form-data
, Ce qui signifie que vous pouvez envoyer plusieurs champs de formulaire et des métadonnées comme les noms de champs et de fichiers seront également transmis. Vous pouvez également modifier l'objet FormData
avant de l'envoyer. Selon la structure côté serveur, le traitement de cette demande peut être plus simple que les données brutes, il existe généralement de nombreux assistants que vous pouvez utiliser. Compatibilité du navigateur : Chrome 6, Firefox 4, Opera 12, IE 10.Vous pouvez écouter les événements progress
sur XMLHttpRequest.upload
. Les progress
événements ont des propriétés loaded
et total
qui permettent de déterminer jusqu'où vous en êtes avec votre demande. Compatibilité du navigateur : Chrome 7, Firefox 3.5, Opera 11.60, IE 10.
Il existe bien sûr des bibliothèques existantes qui regroupent les fonctionnalités décrites ici. Ceux-ci sont mentionnés dans d'autres réponses, la recherche sur le Web apparaîtra certainement encore plus. Je ne veux explicitement proposer aucune bibliothèque ici - laquelle d'entre elles, le cas échéant, vous devriez utiliser est purement une question de préférence.
Ma réponse est assez tardive mais voilà:
XMLHttpRequest est le meilleur moyen de télécharger des fichiers dans un navigateur moderne.
Qu'est-ce que XMLHttpRequest?
XMLHttpRequest est un objet JavaScript conçu par Microsoft et adopté par Mozilla, Apple et Google. C'est maintenant normalisé dans le W3C . Il fournit un moyen simple de récupérer des données à partir d'une URL sans avoir à effectuer une actualisation complète de la page. Une page Web peut mettre à jour seulement une partie de la page sans perturber ce que fait l'utilisateur. XMLHttpRequest est largement utilisé dans la programmation AJAX .
Malgré son nom, XMLHttpRequest peut être utilisé pour récupérer tout type de données, pas seulement XML , et il prend en charge des protocoles autres que HTTP (y compris fichier et ftp ).
L'objet XMLHttpRequest
a fait peau neuve dans les spécifications Html5 . Plus précisément XMLHttpRequest niveau 2 .
Conformément à la spécification Html5 Progress Events , l'événement de progression Html5 fournit, entre autres, les informations suivantes:
total - Total bytes being transferred
loaded - Bytes uploaded thus far
lengthComputable - Specifies if the total size of the data/file being uploaded is known
En utilisant les informations ci-dessus, il est assez facile de fournir les informations "Temps restant" à l'utilisateur.
Informations sur le fichier pouvant être mis à la disposition de l'utilisateur:
Veuillez vérifier " Téléchargement de fichiers en utilisant Html5 avec la démonstration d'indication de progression " pour un exemple. Tout le code JavaScript requis est dans la page mais aucun CSS n'est inclus. Pour des raisons de sécurité, les types de fichiers sont limités à jpg, png, gif et txt. La taille maximale du fichier est de 2 Mo.
L'API de fichier Javascript est probablement le meilleur moyen dans les navigateurs modernes:
http://www.sitepoint.com/html5-javascript-file-upload-progress-bar/
Côté serveur ... Je pense que l'un des principaux frameworks a le fichier HTTP POST fonctionnalité bien couverte.
Personnellement, j'aime le plugin Blueimp jQuery File Upload ( https://blueimp.github.io/jQuery-File-Upload/ )
Widget de téléchargement de fichiers avec sélection de fichiers multiples, prise en charge du glisser-déposer, barres de progression, images de validation et d'aperçu, audio et vidéo pour jQuery. Prend en charge les téléchargements de fichiers inter-domaines, fragmentés et pouvant être repris et le redimensionnement d'image côté client. Fonctionne avec n'importe quelle plate-forme côté serveur (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) qui prend en charge les téléchargements de fichiers de formulaire HTML standard.
Démos:
Télécharger (GitHub): https://github.com/blueimp/jQuery-File-Upload
Les fichiers peuvent être téléchargés via AJAX.
Utilisez le plugin de formulaire jQuery . Il fait tout le sale boulot de lier les fichiers au formulaire et de le sérialiser. Il est également capable d'afficher la progression du téléchargement.
La pile de serveurs n'a pas grand-chose à voir avec cela.