J’ai réalisé (en me regardant) qu’il ya beaucoup de démos et de tutoriels qui vous montrent comment faire glisser et déposer un fichier dans le navigateur, puis le rendre sur la page. Ils sont souvent étiquetés comme « drag-and-drop et télécharger », mais ils ne téléchargent pas. Ce tutoriel vous prendra cette dernière étape.
Je vais vous donner un exemple avec qui vous pouvez jouer : faites glisser un fichier dans la page Web, et il sera téléchargé instantanément sur le serveur.
Tâches #
Brisons ce processus en tâches spécifiques :
- Capturez l’événement drop et lisez ses données.
- Affichez ces données binaires sur le serveur.
- Fournir des commentaires sur les progrès du téléchargement.
- Rendre en option un aperçu de ce qui est téléchargé et de son statut.
Pour y parvenir, nous avons besoin des API HTML5 et non HTML5 suivantes :
Gardez à l’esprit que tous les navigateurs ne supportent pas toute cette technologie aujourd’hui, mais ils se rapprochent. Je voulais juste créer un tutoriel clair et complet sur la façon d’aller l’ensemble du porc et télécharger ce fichier abandonné.
Le résultat final: nous sommes en mesure de laisser tomber le fichier n’importe où dans le navigateur, nous obtenons un aperçu et des progrès du téléchargement, et c’est une expérience lisse.

Glisser et laisser tomber #
Tout comme un avertissement, drag-and-drop a été connu pour être un peu un killjoy. En fait, c’est un cauchemar, mais je ne répéterai pas ce qui a été dit avant.
Notre exemple va vous permettre de faire glisser et déposer un fichier n’importe où dans le navigateur. Pour ce faire, nous devons attacher nos auditeurs d’événements au co
rps
ou d
ocumenterElement
(c.-à-d., le nœud HTML racine). En écoutant le docum
entElement, ce
code peut être n’importe où dans la page, car
documentElement
existera toujours. Vous ne pouvez écouter sur le
corp
s qu’une fois
que le
<body>l’élément a été rencontré.</body>
Voici le modèle de code dont nous avons besoin pour capturer l’événement drop sur l’ensemble du document :
var doc = document.documentElement; doc.ondragover = fonction () { this.className = 'hover';return false; }; doc.ondragend = fonction () { this.className = ''; returnfalse; }; doc.ondrop = fonction (événement) { event.preventDefault && event.preventDefault(); this.className = ''; maintenant faire quelque chose avec: var fichiers = event.dataTransfer.files; revenir faux; };
J’utilise la clas
se hov
er afin que je puisse basculer un pourboire expliquant à l’utilisateur que le fichier peut être laissé tomber sur la page.
À l’intérieur
de l’
événement drop, nous pouvons accéder aux fichiers abando
nnés viaevent.dataTransfer.file
s.
Une alternative au drag and drop #
Ennuyeusement, comme je l’écris ceci, je me rends compte que cette combinaison d’exigences api est actuellement seulement remplie par Chrome et Firefox. Ainsi, en prenant le test de Modernizr, nous pouvons tester pour le soutien et fournir notre alternative:
var dndSupported = fonction () { var div = document.createElement('div'); retour ('draggable' en div) || ('ondragstart' in div &&'ondrop' in div); }; si (!dndSupported()) { // prendre un itinéraire alternatif }
Au lieu de glisser-déposer, nous pouvons insérer un élément d’entrée de fichier (je lui ai donné
u
n id de « upload »), et lorsque sa valeur est modifiée, le fichier peut être ramassé dans:
document.getElementById ('upload').onchange = fonction (événement){ // 'ceci' se réfère à l’élément que l’événement a tiré sur les fichiers var = this.files; };
Vous pouvez voir l’équivalent est simplement
la pr
opriété fichiers d
e l’objet HTMLInpu
tElement. Cela nous donnera accès au même fichier que l’e
vent.dataTransfer.files
de l’événement drop.
Téléchargement automatique du fichier #
C’est le peu soigné, et c’est douloureusement simple. Nous utilisons une fonctionnalité de la spécification
XHR2: FormDat
a. Une fois que nous créons une instance de
FormData,
nous pouvons y annexer des éléments :
var formData = nouvelle FormData(); pour (var i = 0; i < files.length; i++) { formData.append('file', [i]files); } // now post a new XHR request var xhr = new XMLHttpRequest(); xhr.open('POST', '/upload'); xhr.onload = function () { if (xhr.status === 200) { console.log('all done: ' + xhr.status); } else { console.log('Something went terribly wrong...'); } }; xhr.send (formData);
e FormData
Ouais, c’est tout.†
Examinons quelques éléments clés qui se trouvent sur le code ci-dessus.
formData.append (« fichier », fichier[i]s);
Nous envoyons des paramètres nommés à notre serveur, en particulier un éventail de valeurs appelées fi
chie
r. Évidemment, vous pouvez l’appeler ce que vous voulez, mais le f
ichie
r est le nom que votre serveur sera à la recherche quand il enregistre le fichier téléchargé (ou des fichiers).
xhr.onload = fonction () { if (xhr.status === 200) { console.log ('all done: ' + xhr.status); } d’autre { console.log ('Quelque chose s’est terriblement mal passé...'); } };
Si vous êtes familier avec XHR, vous remarquerez que nous n’écoutons pas
onreadystatechange,
seulemen
t onloa
d – qui est (en effet) une fonction de commodité pour vous faire savoir quand le
readyState
est 4 (c.-à-d., chargé!). Vous devez toujours vérifier et répondre de manière appropriée au code d’état de la demande pour vous assurer qu’il est 200 OK, plutôt que d’un 500 (erreur serveur interne) ou 404 (non trouvé) ou quoi que ce soit d’autre.
xhr.send (formData);
La belle astuce ici est que XHR a automatiquement défini l’encodage des données affichées à multipar
t / formulaire-donnée
s. Cet encodage permet à votre serveur de lire et d’enregistrer les fichiers. C’est comme l’encodage utilisé lorsque vous envoyez une pièce jointe dans un e-mail.
Fournir des commentaires à l’utilisateur #
XHR2 maintenant (flippin ' enfin) est livré avec un é
vénement d
e progrès. Donc, si vous envoyez ou récupérez un gros fichier via XHR, vous pouvez dire à l’utilisateur jusqu’où vous êtes.
C’est assez simple. Si vous souhaitez suivre l’évolution de la demande XHR, écoutez l’événemen
t de prog
ression. Un gotcha qui m’a surpris pendant un certain temps: j’avais besoin de suivre les progrès du téléchargement, pas le téléchargement. Pour ce faire correctement, vous devez écouter les progrès sur l’objet de téléchargement XHR, comme si:
xhr.upload.onprogress = fonction (événement) { if (event.lengthComputable) { var complete = (event.loaded / event.total * 100 | 0); progress.value = progress.innerHTML = complet; } }; xhr.onload = fonction () { // juste au cas où nous resterions coincés autour de 99% progress.value = progress.innerHTML = 100; };
de progrès
de XHR2Notez qu’au lieu de xhr
.onprogress, no
us utilis
onsxhr.upload.onproges
s. Lorsque cet événement se déclenche, nous vérifions que l’événement prend en charge le calcul de la quantité de données té
léchargées (la parti
e thelengthComputable), puis calculons le montant complété.
Dans mon HTML, j’utilise un
<progress>é
lément (similaire à l’élémen
t,<meter>
mais plus sémantiquement approprié que nous présentons les progrès d’une tâche) pour montrer à l’utilisateur combien de leur fichier a été téléchargé:</meter> </progress>
<progress id="progress" min="0" max="100" value="0">0</progress>
Notez que j’utilise innerH
TML pour les
navigateurs qui ne supportent pas encore<progre
ss>.</progres
s> Ensuite, avec un soupçon de contenu généré par le CSS,
l’innerH
TML e
t la v
aleur du progrès peuvent être les mêmes (peut-être une sur-optimisation, mais j’étais plutôt fier de moi à l’époque!).
Et enfin, rendre un aperçu #
Comme un ajout agréable, nous allons donner à l’utilisateur un aperçu de ce que nous téléchargeons pour eux. Il nécessite l’API fichier – en particulier
l’APIFileR
eader.
Comme l’opération glisser-déposer (ou l’e
ntrée)[type=file]
contient un objet de fichier, nous pouvons le remettre au
FileReader
pour obtenir le contenu du fichier. Si c’est quelque chose comme une image, nous pouvons obtenir les données Base64 et donner à l’utilisateur un aperçu. Ou si c’est du texte, nous pourrions le rendre dans un<di
v>.</di
v> Le type MIME pour le fichier est disponible sous forme
de pr
opriété type sur l’objet de fichier.
Supposons donc que nous n’acceptons que les images. Voici la partie aperçu qui s’exécute après que le fichier a été reçu par le navigateur:
var acceptedTypes = { 'image/png': vrai, 'image/jpeg': vrai, 'image/gif': vrai }; if (acceptedTypes ===[file.type] true) { var reader = new FileReader(); reader.onload = fonction (événement) { image var = nouvelle image(); image.src = event.target.result; image.width = 100; un faux document resize.body.appendChild (image); }; reader.readAsDataURL (fichier); }
Nous créons le
FileReader e
t lui donnons un fichier à lire. Dans l’exemple ci-dessus, j’ai utilisé r
eadAsDataURL, mai
s vous pouvez également lire des fichiers en texte clair et formats binaires (selon les spécifications).
Lorsque le lecteur a lu le fichier et que les données sont disponibles, il déclenche l’é
véne
mentload, ce qui crée à son tour notre nouvelle image.
Le résultat de l’action de lecture de fichier est dan
s le event.target.resu
ltproperty. Dans le cas de la re
adAsDataURL, l
a valeur est le long des lignes de d
onnées:image/png;base64,ABC..
..
Utilisation de tous les outils dans le hangar #
Cet exemple peut être un peu artificiel pour l’article que je voulais écrire. J’ai utilisé de nombreuses technologies différentes pour faire quelque chose qui est un modèle assez commun sur le web. En fait, c’est parce que j’ai eu du mal à trouver une source définitive sur le téléchargement sur le serveur réel (sauf, bien sûr, comme je l’ai écrit cet article, j’ai trouvé cet exemple de retour à la fin de 2010!).
Espérons que vous verrez comment chaque bit de technologie peut travailler ensemble pour créer une application, mais j’espère également que vous pouvez voir où cela fonctionnerait si aucun ou juste une partie de la technologie n’était pas disponible. Assurez-vous de détecter les fonctionnalités. Assurez-vous de fournir des retombées. Assurez-vous de vous développer de façon responsable.
Voici la dernière démo de drag-and-drop et de téléchargement avec qui vous pouvez jouer.