Upload JS et File API
Notes de cours
Travail personnel
Objectifs
Ce TP va vous faire manipuler l'upload en JS ainsi que l'API « File » et divers aspects y afférents.
Exercice 1 — Upload en JS #
Créer une page HTML avec un widget permettant d'uploader un fichier, ainsi qu'une barre de progression HTML.
A priori pas besoin de récupérer les données côté serveur, puisque seule la partie client nous intéresse ici. On pourra utiliser l'URL de cette page pour la destination de l'upload.
Affichage de la progression de l'upload
Faire en sorte que lors de l'upload, la barre de progression reflète l'état courant de l'upload (c'est-à-dire la proportion du fichier qui a déjà été transmise). Pour cela il faut déclencher l'upload en JS avec un XHR, ce qui permet d'écouter l'événementprogress
sur le XHR.
Important : s'assurer que l'upload fonctionne avec ou sans JS ! La barre de progression n'est qu'une amélioration, pas un aspect essentiel de la page : elle ne mérite absolument pas de rendre la page inutilisable sans JS.
Affichage d'une miniature
- Lors de l'upload, la page doit afficher le type MIME du fichier. On peut le récupérer via l'instance de
File
récupérable dans l'attributfiles
du widget d'upload. - S'il s'agit d'un fichier texte, la page doit afficher aussi le début du texte (par exemple les 100 premiers caractères). Pour cela, il faut créer un FileReader
et utiliser sa méthode
readAsText
. Attention, la méthode ne renvoie pas le texte, elle est asynchrone : il faut écouter l'événementload
sur le FileReader. - S'il s'agit d'une image, la page doit afficher à côté du type MIME une miniature de l'image (maximum 100 pixels par 100 pixels — attention à ne pas la déformer !).
Pour ce faire, on utilisera deux techniques :
- tout d'abord une data-URL, grâce à la méthode
readAsDataURL
de FileReader. Cette URL contient véritablement l'image (encodée en base 64) : si vous copiez l'URL et que vous l'ouvrez avec un autre navigateur, ou l'envoyez par mail, l'image s'affichera sans problème. Tester ! NB : la longueur de l'URL est proportionnelle au poids de l'image… - puis une blob-URL, avec la méthode
window.URL.createObjectURL
. C'est beaucoup plus efficace, car une blob-URL n'est qu'une façon d'accéder à un fichier manipulé par le navigateur (on peut la voir comme un pointeur vers l'image dans la mémoire du navigateur). Cependant la blob-URL ne fonctionne que tant que la page est ouverte. Tester l'URL dans un autre navigateur : ça ne marchera pas. NB : pour éviter de consommer des ressources inutilement, il faut révoquer la blob-URL dès que la miniature a fini de se charger : appelerwindow.URL.revokeObjectURL
dans un capteur d'événementload
sur la miniature.
- tout d'abord une data-URL, grâce à la méthode
Exercice 2 — Hexdump #
Le but de cet exercice est de créer une application web légère
(c'est-à-dire tournant uniquement sur la machine cliente)
reproduisant la commande Unix hd
(hexdump -C
),
qui affiche les octets d'un fichier ou de l'entrée standard.
Exemples d'utilisation de hd
sur le fichier nyan.png
(qui contient l'image suivante : ) et sur une chaîne de caractères :
$ hd nyan.png | head 00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| 00000010 00 00 00 32 00 00 00 32 04 03 00 00 00 ec 11 95 |...2...2........| 00000020 82 00 00 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 |.....gAMA......a| 00000030 05 00 00 00 20 63 48 52 4d 00 00 7a 26 00 00 80 |.... cHRM..z&...| 00000040 84 00 00 fa 00 00 00 80 e8 00 00 75 30 00 00 ea |...........u0...| 00000050 60 00 00 3a 98 00 00 17 70 9c ba 51 3c 00 00 00 |`..:....p..Q<...| 00000060 2d 50 4c 54 45 ff ff ff ff 00 00 00 00 00 ff cc |-PLTE...........| 00000070 99 ff 99 00 ff 99 ff ff 33 99 ff ff 00 99 99 99 |........3.......| 00000080 33 ff 00 00 99 ff bd ff f7 ff 99 99 66 33 ff ff |3...........f3..| 00000090 ff ff 35 e5 ab 90 00 00 00 01 74 52 4e 53 00 40 |..5.......tRNS.@| $ echo 'Une chaîne de caractères en UTF-8 avec > un saut de ligne et 🐳 une baleine' | hd 00000000 55 6e 65 20 63 68 61 c3 ae 6e 65 20 64 65 20 63 |Une cha..ne de c| 00000010 61 72 61 63 74 c3 a8 72 65 73 20 65 6e 20 55 54 |aract..res en UT| 00000020 46 2d 38 20 61 76 65 63 0a 75 6e 20 73 61 75 74 |F-8 avec.un saut| 00000030 20 64 65 20 6c 69 67 6e 65 20 65 74 20 f0 9f 90 | de ligne et ...| 00000040 b3 20 75 6e 65 20 62 61 6c 65 69 6e 65 0a |. une baleine.| 0000004e $
Chaque ligne présente 16 octets, sous forme hexadécimale (au milieu) et au format ASCII (à droite). Le nombre en début de ligne est la position (en hexadécimal) du premier octet de la ligne dans le fichier (son offset). La partie de droite remplace les caractères hors ASCII ou non imprimables par un point.
Reproduction de hd
- Créer une page HTML avec un formulaire permettant d'uploader un fichier
et un élément
output
qui servira à afficher les sorties. - Faire en sorte que lors de la validation du formulaire, la zone de sortie affiche le nom du fichier, sa taille et son type MIME.
- Si le fichier est textuel (regarder le type MIME), la zone de sortie doit afficher le contenu du fichier au format texte, interprété comme de l'UTF-8. Essayer avec ce fichier texte.
- Dans tous les cas, la validation du formulaire doit ajouter à la zone de sortie
un élément
pre
avec les octets du fichier :- tout d'abord, sous la forme de nombres décimaux entre 0 et 255 ;
- et ensuite sous forme de paires de chiffres hexadécimaux
- Ajouter à côté de chaque octet sa « forme ASCII » entre parenthèses, en remplaçant les caractères hors ASCII ou non imprimables par un caractère spécial de votre choix.
Ajout d'interactivité
On va rendre notre outil un peu plus interactif.
- Au lieu d'afficher le dump au format texte,
chaque octet doit correspondre à un
span
contenant l'hexadécimal (et le format ASCII). Attention : ne tester que sur des petits fichiers ! (Ou limiter l'affichage aux 1024 premiers octets…) - Optionnel : des cases à cocher permettent de contrôler ce qui est affiché, hexadécimal, ASCII ou les deux.)
- Transformer l'application en un éditeur hexadécimal : cliquer sur un octet augmente sa valeur de 1. Attention, le format ASCII de l'octet, et le contenu textuel du fichier le cas échéant, doivent être mis à jour en temps réel.
- Un bouton « Télécharger le résultat » doit permettre de récupérer le fichier modifié.
- Optionnel : on peut modifier chaque octet au clavier (transformer le
span
eninput
au clic, ou utiliser l'attributcontenteditable
) - Optionnel : rendre possible l'édition de gros fichiers, en ne construisant les
span
qu'à la volée, par groupes de 1024.