Upload JS et File API

Master Internet, Données et Connaissances

Alexandre Niveau

Enseignement des technologies du Web

 

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énement progress 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

  1. 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'attribut files du widget d'upload.
  2. 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énement load sur le FileReader.
  3. 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 : appeler window.URL.revokeObjectURL dans un capteur d'événement load sur la miniature.

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 : nyan cat) 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

  1. Créer une page HTML avec un formulaire permettant d'uploader un fichier et un élément output qui servira à afficher les sorties.
  2. 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.
  3. 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.
  4. Dans tous les cas, la validation du formulaire doit ajouter à la zone de sortie un élément pre avec les octets du fichier :
    1. tout d'abord, sous la forme de nombres décimaux entre 0 et 255 ;
    2. et ensuite sous forme de paires de chiffres hexadécimaux
  5. 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.

  1. 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…)
  2. Optionnel : des cases à cocher permettent de contrôler ce qui est affiché, hexadécimal, ASCII ou les deux.)
  3. 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.
  4. Un bouton « Télécharger le résultat » doit permettre de récupérer le fichier modifié.
  5. Optionnel : on peut modifier chaque octet au clavier (transformer le span en input au clic, ou utiliser l'attribut contenteditable)
  6. Optionnel : rendre possible l'édition de gros fichiers, en ne construisant les span qu'à la volée, par groupes de 1024.