web-dev-qa-db-fra.com

Quelle est la meilleure façon de télécharger des fichiers dans un navigateur moderne

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.

62
Tom

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).

XMLHttpRequest vs sockets Web vs autre chose

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.

Envoi de données binaires

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:

  • Envoi uniquement du contenu du fichier: 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.
  • Envoi des données de l'ensemble du formulaire : 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.
  • Envoi d'un tableau typé : juste au cas où vous n'avez pas de fichier mais voulez simplement envoyer des données binaires que vous générez à la volée. Aucun encodage supplémentaire n'est effectué ici, donc en ce qui concerne le côté serveur, cela fonctionne comme l'envoi du contenu du fichier. Compatibilité du navigateur : Chrome 9, Firefox 9, Opera 11.60, IE 10.

Affichage de la progression du téléchargement

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.

Bibliothèques JavaScript

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.

60
Wladimir Palant

Ma réponse est assez tardive mais voilà:


Réponse courte:

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 .


Avantages:

  • Gestion des flux d'octets tels que Fichier , Blob et Objets FormData pour le téléchargement et le téléchargement
  • Événements de progression pendant le téléchargement et le téléchargement
  • Demandes d'origine croisée
  • Autoriser la création d'une demande anonyme - qui ne permet pas d'envoyer HTTP Referer
  • La possibilité de définir un Timeout pour la demande
  • Le téléchargement se déroule en arrière-plan
  • La page sur laquelle l'utilisateur se trouve reste intacte
  • Ne nécessite aucune modification côté serveur , la logique côté serveur existante doit donc rester inchangée, ce qui rend l'adaptation de cette technologie beaucoup plus facile.

L'événement de progression Html5:

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.


Tenez l'utilisateur informé:

Informations sur le fichier pouvant être mis à la disposition de l'utilisateur:

  1. Nom de fichier
  2. Taille du fichier
  3. Type de mime
  4. Une barre de progression avec pourcentage achevé
  5. La vitesse de téléchargement ou la bande passante de téléchargement
  6. Le temps approximatif restant
  7. Les octets téléchargés jusqu'à présent
  8. Une réponse du côté serveur

Téléchargement de fichiers à l'aide de la démo XMLHttpRequest

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.


Compatibilité du navigateur XMLHttpRequest:

XMLHttpRequest Browser compatibility


19
Pedro Lobito

L'API de fichier Javascript est probablement le meilleur moyen dans les navigateurs modernes:

http://robertnyman.com/2010/12/16/utilizing-the-html5-file-api-to-choose-upload-preview-and-see-progress-for-multiple-files/ =

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.

5
vtortola

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

4
ptCoder

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.

Démo

4
xyres