Fermer

mars 2, 2020

Comment créer un formulaire de téléchargement de fichiers avec Express et DropzoneJS –


Regardons les choses en face, personne n'aime les formes. Les développeurs n'aiment pas les construire, les concepteurs n'aiment pas particulièrement les styliser, et les utilisateurs n'aiment certainement pas les remplir.

De tous les composants qui peuvent constituer un formulaire, le contrôle de fichier pourrait être le plus frustrant du lot. C'est un vrai problème de style, il est maladroit et maladroit à utiliser, et le téléchargement d'un fichier ralentira le processus de soumission de n'importe quel formulaire.

C'est pourquoi un plugin pour les améliorer vaut toujours le coup d'oeil, et DropzoneJS n'est qu'une de ces options. Cela améliorera l'apparence de vos contrôles de téléchargement de fichiers, les rendra plus conviviaux et, en utilisant AJAX pour télécharger le fichier en arrière-plan, il rendra à tout le moins le processus plus rapide . Cela permet également de valider plus facilement les fichiers avant même qu'ils n'atteignent votre serveur, fournissant un retour d'information presque instantané à l'utilisateur.

Nous allons jeter un œil à DropzoneJS en détail. Nous allons montrer comment l'implémenter. et regardez quelques-unes des façons dont il peut être modifié et personnalisé. Nous implémenterons également un mécanisme de téléchargement simple côté serveur à l'aide de Node.js.

Comme toujours, vous pouvez trouver le code de ce didacticiel sur notre référentiel GitHub .

Cet article a été mis à jour en 2020. Pour en savoir plus sur Node.js, lisez Développement Web Node.js – Quatrième édition .

Présentation de DropzoneJS

DropzoneJS permet aux utilisateurs de télécharger des fichiers par glisser-déposer. Alors que les avantages de l'utilisabilité pourraient être discutés à juste titre c'est une approche de plus en plus courante et qui est en phase avec la façon dont beaucoup de gens travaillent avec des fichiers sur leur bureau. Il est également assez bien pris en charge sur les principaux navigateurs.

DropzoneJS n'est pas simplement un widget basé sur le glisser-déposer. Le fait de cliquer sur le widget lance l'approche de dialogue de sélection de fichier la plus conventionnelle.

Voici une animation du widget en action:

 Le widget DropzoneJS en action

Alternativement, jetez un œil à cet exemple le plus minime .

Vous pouvez utiliser DropzoneJS pour tout type de fichier, bien que le joli petit effet de vignette le rend idéalement adapté pour télécharger des images en particulier.

Caractéristiques

Pour résumer certaines des Fonctionnalités et caractéristiques du plugin, DropzoneJS:

  • peut être utilisé avec ou sans jQuery
  • prend en charge le glisser-déposer
  • génère des images miniatures
  • prend en charge plusieurs téléchargements, éventuellement en parallèle
  • inclut une progression la barre
  • est entièrement thématisable
  • comprend une prise en charge extensible de la validation des fichiers
  • est disponible en tant que module AMD ou module RequireJS
  • arrive à environ 43 Ko lorsque minifié et 13 Ko lorsqu'il est compressé

Support du navigateur [19659015] Tiré de la documentation officielle, le support du navigateur est le suivant:

  • Chrome 7+
  • Firefox 4+
  • IE 10+
  • Opera 12+ (la version 12 pour macOS est désactivée car leur API est boguée )
  • Safari 6+

Il existe plusieurs façons de gérer les solutions de secours lorsque le plug-in n'est pas entièrement pris en charge, que nous verrons plus tard.

Mise en place

La façon la plus simple de commencer avec DropzoneJS, c'est inclure la dernière version d'un CDN . Au moment de la rédaction, il s'agit de la version 5.5.1 .

Alternativement, vous pouvez télécharger la dernière version à partir de la page GitLab du projet . Il existe également un package tiers prenant en charge ReactJS .

Ensuite, assurez-vous d'inclure à la fois le fichier JavaScript principal et les styles CSS dans votre page. Par exemple:




  
   Exemple de téléchargement de fichier 
  

  

Notez que le projet fournit deux fichiers CSS – un fichier basic.css avec un style minimal et un fichier plus étendu dropzone.css fichier. Des versions réduites de dropzone.css et dropzone.js sont également disponibles.

Utilisation de base

La manière la plus simple d'implémenter le plug-in est de l'attacher à un formulaire, bien que vous pouvez utiliser n'importe quel code HTML tel qu'un

. Cependant, l'utilisation d'un formulaire signifie moins d'options à définir, notamment l'URL, qui est la propriété de configuration la plus importante.

Vous pouvez l'initialiser simplement en ajoutant la classe dropzone . Par exemple:

Techniquement, c'est tout ce que vous devez faire, bien que dans la plupart des cas, vous souhaitiez définir des options supplémentaires. Le format est le suivant:

 Dropzone.options.WIDGET_ID = {
  //
};

Pour dériver l'ID de widget pour définir les options, prenez l'ID que vous avez défini dans votre code HTML et mettez-le dans une case camel. Par exemple, upload-widget devient uploadWidget :

 Dropzone.options.uploadWidget = {
  //
};

Vous pouvez également créer une instance par programme:

 const uploader = new Dropzone ('# upload-widget', options);

Ensuite, nous allons examiner certaines des options de configuration disponibles.

Options de configuration de base

L'option url définit la cible du formulaire de téléchargement et est le seul paramètre requis. . Cela dit, si vous l'attachez à un élément de formulaire, il utilisera simplement l'attribut d'action du formulaire auquel cas vous n'avez même pas besoin de le spécifier.

Le L'option method définit la méthode HTTP et encore une fois, elle prendra cela de l'élément de formulaire si vous utilisez cette approche, sinon elle sera simplement par défaut à POST ce qui devrait convenir à la plupart des scénarios. [19659003] L'option paramName est utilisée pour définir le nom du paramètre du fichier téléchargé. Si vous utilisez un élément de formulaire de téléchargement de fichier, il correspondra à l'attribut nom . Si vous ne l'incluez pas, le fichier par défaut est .

maxFiles définit le nombre maximal de fichiers qu'un utilisateur peut télécharger, s'il n'est pas défini sur null.

Par défaut, le widget affichera une boîte de dialogue de fichier lorsqu'il est cliqué, bien que vous puissiez utiliser le paramètre cliquable pour le désactiver en le réglant sur false ou bien vous pouvez fournir un élément HTML ou sélecteur CSS pour personnaliser l'élément cliquable.

Ce sont les options de base, mais regardons maintenant certaines des options les plus avancées.

Application de la taille maximale du fichier

La propriété maxFilesize détermine la taille maximale du fichier en mégaoctets. Cette valeur par défaut est de 1 000 octets, mais en utilisant la propriété filesizeBase vous pouvez lui attribuer une autre valeur, par exemple 1 024 octets. Vous devrez peut-être modifier cela pour vous assurer que votre code client et serveur calculent précisément toutes les limites de la même manière.

Restriction à certains types de fichiers

Le paramètre acceptéFiles peut être utilisé pour restreindre le type du fichier que vous souhaitez accepter. Cela devrait prendre la forme d'une liste de types MIME séparés par des virgules, bien que vous puissiez également utiliser des caractères génériques.

Par exemple, pour n'accepter que des images:

 acceptéFiles: 'image / *',

Modification de la taille de la miniature

Par défaut, la miniature est générée à 120x120px. Autrement dit, c'est carré. Vous pouvez modifier ce comportement de plusieurs manières.

La première consiste à utiliser les options de configuration thumbnailWidth et / ou thumbnailHeight .

Si vous définissez les deux thumbnailWidth et thumbnailHeight à null la vignette ne sera pas du tout redimensionnée.

Si vous souhaitez personnaliser complètement le comportement de génération de vignettes, vous pouvez même remplacer la fonction resize .

Un point important concernant la modification de la taille de la vignette est que la classe dz-image fournie par le package définit la taille de la vignette dans le CSS, donc vous devrez également modifier cela en conséquence.

Vérifications de fichiers supplémentaires

L'option accepter vous permet de fournir des vérifications supplémentaires pour déterminer si un fichier est valide avant d'être téléchargé. Vous ne devez pas l'utiliser pour vérifier le nombre de fichiers ( maxFiles ), le type de fichier ( acceptéFiles ) ou la taille de fichier ( maxFilesize ), mais vous pouvez écrire du code personnalisé pour effectuer d'autres types de validation.

Vous utiliseriez l'option accepter comme ceci:

 accept: function (fichier, fait) {
  if (! someCheck ()) {
    retour effectué ('Ceci n'est pas valide!');
  }
  retour fait ();
}

Comme vous pouvez le voir, il est asynchrone. Vous pouvez appeler done () sans arguments ni passes de validation, ou fournir un message d'erreur et le fichier sera rejeté, affichant le message à côté du fichier sous forme de popover.

Nous examinerons un un exemple plus complexe et réel plus tard, lorsque nous verrons comment appliquer des tailles d'image minimales ou maximales.

Souvent, vous devrez attacher des en-têtes supplémentaires à la demande HTTP de l'uploader.

Par exemple, une approche pour La protection CSRF (contrefaçon de demande intersite) consiste à sortir un jeton dans la vue, puis à demander à vos points d'extrémité POST / PUT / DELETE de vérifier les en-têtes de demande pour un jeton valide. Supposons que vous ayez sorti votre jeton comme ceci:

  

Ensuite, vous pouvez ajouter ceci à la configuration:

 en-têtes: {
  'x-csrf-token': document.querySelector ('meta [name=csrf-token]'). getAttributeNode ('content'). value,
},

Alternativement, voici le même exemple mais en utilisant jQuery:

 en-têtes: {
  'x-csrf-token': $ ('meta [name="csrf-token"]'). attr ('content')
},

Votre serveur doit alors vérifier l'en-tête x-csrf-token peut-être en utilisant un middleware . insérez un

dans votre formulaire contenant des contrôles d'entrée, définissant le nom de classe de l'élément sur fallback . Par exemple:

  
  
       

Alternativement, vous pouvez fournir une fonction à exécuter lorsque le navigateur ne prend pas en charge le plug-in à l'aide du paramètre de configuration fallback .

Vous pouvez forcer le widget à utiliser le comportement de secours en définissant forceFallback à true ce qui pourrait être utile lors du développement.

Gestion des erreurs

Vous pouvez personnaliser la façon dont le widget gère les erreurs en fournissant une fonction personnalisée à l'aide de l'erreur paramètre de configuration. Le premier argument est le fichier, le message d'erreur le second, et si l'erreur s'est produite côté serveur, le troisième paramètre sera une instance de XMLHttpRequest .

Comme toujours, la validation côté client n'est que la moitié de la bataille. Vous devez également effectuer la validation sur le serveur. Lorsque nous implémenterons un simple composant côté serveur plus tard, nous examinerons le format attendu de la réponse d'erreur, qui, lorsqu'il est correctement configuré, sera affiché de la même manière que les erreurs côté client (illustré ci-dessous).

 Affichage des erreurs avec DropzoneJS

Remplacement des messages et de la traduction

Il existe un certain nombre de propriétés de configuration supplémentaires qui définissent les différents messages affichés par le widget. Vous pouvez les utiliser pour personnaliser le texte affiché ou pour les traduire dans une autre langue.

Plus particulièrement, dictDefaultMessage est utilisé pour définir le texte qui apparaît au milieu de la zone de dépôt, avant que quelqu'un sélectionne un fichier à télécharger.

Vous trouverez une liste complète des valeurs de chaîne configurables – qui commencent toutes par dict dans la documentation .

Événements [19659008] Il existe un certain nombre d'événements que vous pouvez écouter afin de personnaliser ou d'améliorer le plug-in.

Il existe deux façons d'écouter un événement. La première consiste à créer un écouteur dans une fonction d'initialisation:

 Dropzone.options.uploadWidget = {
  init: fonction () {
    this.on ('success', fonction (fichier, resp) {
      ...
    });
  },
  ...
};

Voici l'approche alternative, qui est utile si vous décidez de créer l'instance Dropzone par programme:

 const uploader = new Dropzone ('# upload-widget');
uploader.on ('success', fonction (fichier, resp) {
  ...
});

L'aspect le plus notable est peut-être l'événement succès qui se déclenche lorsqu'un fichier a été téléchargé avec succès. Le rappel succès prend deux arguments: le premier un objet fichier et le second une instance de XMLHttpRequest .

Les autres événements utiles incluent addedfile et ] suppriméfichier pour quand un fichier a été ajouté ou supprimé de la liste de téléchargement; miniature qui se déclenche une fois la miniature générée; et uploadprogress que vous pourriez utiliser pour implémenter votre propre indicateur de progression.

Il existe également un tas d'événements qui prennent un objet événement comme paramètre et que vous pouvez utiliser pour personnaliser le comportement du widget lui-même – drop dragstart dragend dragenter dragover et dragleave .

Vous trouverez une liste complète des événements dans la section appropriée de la documentation .

Un exemple de validation plus complexe: dimensions de l'image

Plus tôt, nous avons examiné l'acceptation asynchrone () option que vous pouvez utiliser pour exécuter des vérifications (validation) sur les fichiers avant qu'ils ne soient téléchargés.

Une exigence courante lorsque vous téléchargez des images est d'appliquer des dimensions d'image minimales ou maximales. Nous pouvons le faire avec DropzoneJS, bien que ce soit un peu plus complexe.

Bien que le rappel d'acceptation reçoive un objet fichier, afin de vérifier les dimensions de l'image, nous devons attendre la génération de la miniature, point auquel les dimensions auront été défini sur l'objet fichier. Pour ce faire, nous devons écouter l'événement miniature.

Voici le code. Dans cet exemple, nous vérifions que l'image mesure au moins 640 x 480 pixels avant de la télécharger:

 init: function () {
  this.on ('miniature', fonction (fichier) {
    if (file.accepted! == false) {
      if (file.width <1024 || file.height <768) {
        file.rejectDimensions ();
      }
      autre {
        file.acceptDimensions ();
      }
    }
  });
},
accepter: fonction (fichier, terminé) {
  file.acceptDimensions = done;
  file.rejectDimensions = function () {
    done ('L'image doit mesurer au moins 1024 x 768 pixels');
  };
},

Un exemple complet

Après avoir passé en revue les options, les événements et certaines validations légèrement plus avancées, regardons un exemple complet et relativement complet. Évidemment, nous ne profitons pas de chaque option de configuration disponible, car il y en a tellement – ce qui la rend incroyablement flexible.

Voici le code HTML du formulaire:

  
  
       

Si vous implémentez la protection CSRF, vous souhaiterez peut-être ajouter quelque chose comme ceci à vos dispositions:

  
  
  

Maintenant le JavaScript. Notez que nous n'utilisons pas jQuery!

 Dropzone.options.uploadWidget = {
  paramName: 'fichier',
  maxFilesize: 2, // Mo
  maxFiles: 1,
  dictDefaultMessage: 'Faites glisser une image ici pour la télécharger, ou cliquez pour en sélectionner une',
  en-têtes: {
    'x-csrf-token': document.querySelectorAll ('meta [name=csrf-token]') [0] .getAttributeNode ('content'). value,
  },
  fichiers acceptés: 'image / *',
  init: fonction () {
    this.on ('success', fonction (fichier, resp) {
      console.log (fichier);
      console.log (resp);
    });
    this.on ('miniature', fonction (fichier) {
      if (file.accepted! == false) {
        if (file.width <640 || file.height <480) {
          file.rejectDimensions ();
        }
        autre {
          file.acceptDimensions ();
        }
      }
    });
  },
  accepter: fonction (fichier, terminé) {
    file.acceptDimensions = done;
    file.rejectDimensions = function () {
      done ('L'image doit être au moins 640 x 480px')
    };
  }
};

Un rappel que vous trouverez le code de cet exemple sur notre référentiel GitHub .

J'espère que cela suffira pour vous aider à démarrer dans la plupart des scénarios. Consultez la documentation complète si vous avez besoin de quelque chose de plus complexe.

Thème

Il existe un certain nombre de façons de personnaliser l'apparence du widget, et en effet il est possible de transformer complètement la manière

Pour illustrer à quel point l'apparence est personnalisable, voici une démo du widget modifiée pour ressembler et ressembler exactement au widget jQuery File Upload à l'aide de Bootstrap.

De toute évidence, le moyen le plus simple de modifier l'apparence du widget est d'utiliser CSS. Le widget a une classe de dropzone et ses éléments composants ont des classes préfixées avec dz- – par exemple, dz-clickable pour la zone cliquable à l'intérieur de la dropzone, dz-message pour la légende, dz-preview / dz-image-preview pour envelopper les aperçus de chacun des fichiers téléchargés, etc. Jetez un œil au fichier dropzone.css pour référence.

Vous pouvez également appliquer des styles à l'état de survol – c'est-à-dire lorsque l'utilisateur survole un fichier sur la dropzone avant de relâcher le bouton de la souris. pour lancer le téléchargement. Vous pouvez le faire en stylisant la classe dz-drag-hover qui est ajoutée automatiquement par le plug-in.

Au-delà des modifications CSS, vous pouvez également personnaliser le code HTML qui compose les aperçus en définissant le previewTemplate propriété de configuration. Voici à quoi ressemble le modèle d'aperçu par défaut :

SUPPRIMÉ POUR LA BREVITÉ
SUPPRIMÉ POUR LA BREVITÉ   

Comme vous pouvez le voir, vous obtenez un contrôle complet sur la façon dont les fichiers sont rendus une fois qu'ils ont été mis en file d'attente pour le téléchargement, ainsi que sur les états de réussite et d'échec.

Cela conclut la section sur l'utilisation du plugin DropzoneJS. Pour arrondir, voyons comment le faire fonctionner avec du code côté serveur.

Un simple gestionnaire de téléchargement côté serveur avec Node.js et Express

Naturellement, vous pouvez utiliser n'importe quelle technologie côté serveur pour gérer le téléchargement des dossiers. Afin de montrer comment intégrer votre serveur avec le plugin, nous allons construire un exemple très simple en utilisant Node.js et Express .

Pour gérer le fichier téléchargé lui-même, nous utiliserons Multer un package qui fournit un middleware Express qui le rend vraiment facile. En fait, c'est simple:

 const upload = multer ({dest: 'uploads /'});

app.post ('/ upload', upload.single ('file'), (req, res, next) => {
  // Les métadonnées sur le fichier téléchargé peuvent maintenant être trouvées dans req.file
});

Avant de poursuivre l'implémentation, la question la plus évidente à poser lorsque vous traitez avec un plugin comme DropzoneJS, qui vous fait des demandes dans les coulisses, est: "quel type de réponses attend-il?"

Gestion du téléchargement réussi

Si le processus de téléchargement réussit, la seule exigence, en ce qui concerne votre code côté serveur, est de renvoyer un code de réponse 2xx . Le contenu et le format de votre réponse dépendent entièrement de vous et dépendront probablement de la façon dont vous l'utilisez. Par exemple, vous pouvez renvoyer un objet JSON qui contient un chemin d'accès au fichier téléchargé ou le chemin d'accès à une miniature générée automatiquement. Pour les besoins de cet exemple, nous retournerons simplement le contenu de l'objet fichier – c'est-à-dire un tas de métadonnées fournies par Multer:

 return res.status (200) .send (req.file);

La réponse ressemblera à ceci:

 {fieldname: 'file',
  nom d'origine: 'monfichier.jpg',
  encodage: '7bit',
  mimetype: 'image / jpeg',
  destination: 'uploads /',
  nom de fichier: «fbcc2ddbb0dd11858427d7f0bb2273f5»,
  chemin: 'uploads / fbcc2ddbb0dd11858427d7f0bb2273f5',
  taille: 15458}

Gestion des erreurs de téléchargement

Si votre réponse est au format JSON – c'est-à-dire que votre type de réponse est défini sur application / json – alors le plugin d'erreur par défaut DropzoneJS s'attend à ce que la réponse ressemble à ceci:

 {
  erreur: «Le message d'erreur»
}

Si vous n'utilisez pas JSON, il utilisera simplement le corps de la réponse. Par exemple:

 return res.status (422) .send ('The error message');

Voyons cela en effectuant quelques vérifications de validation sur le fichier téléchargé. Nous dupliquerons simplement les contrôles que nous avons effectués sur le client. N'oubliez pas que la validation côté client n'est jamais suffisante à elle seule.

Pour vérifier que le fichier est une image, nous allons simplement vérifier que le type MIME commence par image / . String.prototype.startsWith () d'ES6 est idéal pour cela.

Voici comment nous pouvons exécuter cette vérification et, en cas d'échec, renvoyer l'erreur au format attendu par le gestionnaire d'erreurs par défaut de Dropzone: [19659044] if (! req.file.mimetype.startsWith ('image /')) {
  return res.status (422) .json ({
    erreur: «Le fichier téléchargé doit être une image»
  });
}

Remarque: J'utilise le code d'état HTTP 422, Entité non traitable, pour l'échec de la validation, mais 400 Bad Request est tout aussi valide. En effet, tout ce qui ne fait pas partie de la plage 2xx fera que le plugin signalera l'erreur.

Vérifions également que l'image est d'une certaine taille. Le package de taille d'image permet d'obtenir très simplement les dimensions d'une image. Vous pouvez l'utiliser de manière asynchrone ou synchrone. Nous utiliserons ce dernier pour simplifier les choses:

 const dimensions = sizeOf (req.file.path);

si ((dimensions.largeur <640) || (dimensions.hauteur <480)) {
  return res.status (422) .json ({
    erreur: «L'image doit mesurer au moins 640 x 480 pixels»
  });
}

Mettons tout cela ensemble dans une (mini) application complète:

 const express = require ('express');
const multer = require ('multer');
const upload = multer ({dest: 'uploads /'});
const sizeOf = require ('image-size');
const exphbs = require ('express-guidbars');

const app = express ();

app.use (express.static (__ dirname + '/ public'));

app.engine ('. hbs', exphbs ({extname: '. hbs'}));
app.set ('moteur de vue', '. hbs');

app.get ('/', (req, res) => {
  return res.render ('index', {layout: false});
});

app.post ('/ upload', upload.single ('file'), (req, res) => {
  if (! req.file.mimetype.startsWith ('image /')) {
    return res.status (422) .json ({
      erreur: «Le fichier téléchargé doit être une image»
    });
  }

  const dimensions = sizeOf (req.file.path);

  if ((dimensions.largeur <640) || (dimensions.hauteur < 480)) {
    return res.status(422).json({
      error :'The image must be at least 640 x 480px'
    });
  }

  return res.status(200).send(req.file);
});

app.listen(8080, () => {
  console.log ('Ecoute express du serveur sur le port 8080');
});

Remarque: par souci de concision, ce code côté serveur n'implémente pas la protection CSRF. Pour cela, vous voudrez peut-être consulter un package comme CSURF .

Vous trouverez ce code, ainsi que les ressources de support telles que la vue, dans le référentiel d'accompagnement .

Et si vous souhaitez en savoir plus sur l'utilisation des formulaires dans Node.js, veuillez lire Formulaires, téléchargement de fichiers et sécurité avec Node.js et Express .

Résumé

Résumé

Résumé [19659008] DropzoneJS est un plugin JavaScript élégant, puissant et hautement personnalisable pour suralimenter vos contrôles de téléchargement de fichiers et effectuer des téléchargements AJAX. Dans ce didacticiel, nous avons examiné un certain nombre d'options disponibles, lors d'événements, et comment procéder pour personnaliser le plug-in. Il y a beaucoup plus que ce qui peut raisonnablement être couvert dans un tutoriel, alors consultez le site officiel si vous voulez en savoir plus. Mais j'espère que cela suffit pour vous aider à démarrer.

Nous avons également créé un composant côté serveur très simple pour gérer les téléchargements de fichiers, montrant comment faire fonctionner les deux en tandem.




Source link