Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Ruby on Rails
Code

Téléchargement de fichiers avec Rails et Dragonfly

by
Difficulty:IntermediateLength:LongLanguages:

French (Français) translation by New Lune (you can also view the original English article)

Il y a quelque temps, j'ai écrit un article Téléchargement de fichiers avec Rails et Shrine qui a expliqué comment introduire une fonctionnalité de téléchargement de fichier dans votre application Rails à l'aide de la gemme Shrine. Il existe cependant un tas de solutions similaires et l'un de mes favoris est Dragonfly—une solution de téléchargement facile à utiliser pour Rails et Rack créée par Mark Evans.

Nous avons couvert cette bibliothèque au début de l'année dernière, mais, comme pour la plupart des logiciels, il est utile de jeter un coup d'œil aux bibliothèques de temps en temps pour voir ce qui a changé et comment nous pouvons l'utiliser dans notre application.

Dans cet article je vais vous guider à travers la configuration de Dragonfly et expliquer comment utiliser ses principales fonctionnalités. Vous apprendrez à:

  • Intégrer Dragonfly dans votre application
  • Configurer des modèles pour travailler avec Dragonfly
  • Introduire un mécanisme de téléchargement de base
  • Introduire des validations
  • Générer des miniatures d'images
  • Effectuer le traitement des fichiers
  • Métadonnées de mémoire pour les fichiers téléchargés
  • Préparer une application pour le déploiement

Pour rendre les choses plus intéressantes, nous allons créer une petite application musicale. Il présentera des albums et des chansons associées qui peuvent être gérées et lues sur le site Web.

Le code source de cet article est disponible sur GitHub. Vous pouvez également consulter la démo de travail de l'application.

Liste et gestion des albums

Pour commencer, créez une nouvelle application Rails sans la suite de tests par défaut:

Pour cet article, j'utiliserai Rails 5, mais la plupart des concepts décrits s'appliquent également aux anciennes versions.

Création du modèle, du contrôleur et des itinéraires

Notre petit site musical contiendra deux modèles: Album et Song. Pour l'instant, créons le premier avec les champs suivants:

  • title (string)—contient le titre de l'album
  • singer (string)—interprète de l'album
  • image_uid (string)—un champ spécial pour stocker l'image d'aperçu de l'album. Ce champ peut être nommé tout ce que vous voulez, mais il doit contenir le suffixe _uid comme indiqué par la documentation Dragonfly.

Créer et appliquer la migration correspondante:

Maintenant, nous allons créer un contrôleur très générique pour gérer les albums avec toutes les actions par défaut:

albums_controller.rb

Enfin, ajoutez les itinéraires:

config/routes.rb

Intégrer Dragonfly

Il est temps pour Dragonfly d'entrer dans les feux de la rampe. Tout d'abord, ajoutez le joyau dans le Gemfile:

Gemfile

Exécutez:

La dernière commande créera un initialiseur nommé dragonfly.rb avec la configuration par défaut. Nous allons mettre de côté pour l'instant, mais vous pouvez lire sur diverses options sur le site officiel de Dragonfly.

La prochaine chose importante à faire est d'équiper notre modèle avec les méthodes de Dragonfly. Cela se fait en utilisant le dragonfly_accessor:

models/album.rb

Notez que je dis ici :image—elle concerne directement la colonne image_uid que nous avons créée dans la section précédente. Si, par exemple, vous avez nommé votre colonne photo_uid, la méthode dragonfly_accessor devrait recevoir :photo comme argument.

Si vous utilisez Rails 4 ou 5, une autre étape importante consiste à marquer le champ :image (pas :image_uid!) comme le permet le contrôleur:

albums_controller.rb

C'est à peu près cela—nous sommes prêts à créer des vues et à commencer à télécharger nos fichiers!

Création de vues

Commencez par la vue d'index:

views/albums/index.html.erb

Maintenant le partiel:

views/albums/_album.html.erb

Il existe deux méthodes Dragonfly à noter ici:

  • album.image.url renvoie le chemin d'accès à l'image.
  • album.image_stored? indique si l'enregistrement a un fichier téléchargé en place.

Maintenant, ajoutez les nouvelles pages et modifiez-les:

views/albums/new.html.erb

views/albums/edit.html.erb

views/albums/_form.html.erb

Le formulaire n'est rien de fantaisie, mais encore une fois notez que nous disons :image, non pas :image_uid, lors du rendu de l'entrée du fichier.

Maintenant, vous pouvez démarrer le serveur et tester la fonctionnalité de téléchargement!

Suppression d'images

Ainsi, les utilisateurs sont capables de créer et de modifier des albums, mais il y a un problème: ils n'ont aucun moyen de supprimer une image, seulement pour le remplacer par un autre. Heureusement, cela est très facile à corriger en introduisant une case à cocher "supprimer image":

views/albums/_form.html.erb

Si l'album a une image associée, nous l'affichons et rendons une case à cocher. Si cette case est cochée, l'image sera supprimée. Notez que si votre champ est nommé photo_uid, la méthode correspondante pour supprimer la pièce jointe sera remove_photo. Simple, n'est-ce pas?

La seule autre chose à faire est de permettre l'attribut remove_image dans votre contrôleur:

albums_controller.rb

Ajout de validations

À ce stade, tout fonctionne bien, mais nous ne vérifions pas du tout l'entrée de l'utilisateur, ce qui n'est pas particulièrement génial. Par conséquent, ajoutons des validations pour le modèle Album:

models/album.rb

validates_property est la méthode Dragonfly qui peut vérifier divers aspects de votre pièce jointe: vous pouvez valider l'extension d'un fichier, le type MIME, la taille, etc.

Maintenant, nous allons créer une partie générique pour rendre les erreurs qui ont été trouvés:

views/shared/_errors.html.erb

Employez ce partiel à l'intérieur du formulaire:

views/albums/_form.html.erb

Créez les champs avec des erreurs un peu pour les représenter visuellement:

stylesheets/application.scss

Retenir une image entre les demandes

Après avoir introduit des validations, nous rencontrons un autre problème (tout un scénario typique, hein?): si l'utilisateur a fait des erreurs tout en remplissant le formulaire, il devra choisir le fichier après avoir cliqué sur le bouton Submit.

Dragonfly peut vous aider à résoudre ce problème en utilisant un champ caché retained_*:

views/albums/_form.html.erb

N'oubliez pas d'autoriser ce champ aussi:

albums_controller.rb

Maintenant l'image sera persisté entre les demandes! Le seul petit problème, cependant, est que l'entrée de téléchargement de fichier affichera toujours le message "choisir un fichier", mais cela peut être corrigé avec un style et un tiret de JavaScript.

Traitement des images

Générer des vignettes

Les images téléchargées par nos utilisateurs peuvent avoir des dimensions très différentes, ce qui peut (et probablement) causer un impact négatif sur la conception du site. Vous voudrez probablement réduire les images à certaines dimensions fixes, et bien sûr cela est possible en utilisant les styles de width et de height. Cependant, ce n'est pas une approche optimale: le navigateur devra quand même télécharger des images en taille réelle, puis les rétrécir.

Une autre option (qui est généralement beaucoup mieux) est de générer des miniatures d'image avec des dimensions prédéfinies sur le serveur. C'est vraiment simple à réaliser avec Dragonfly:

views/albums/_album.html.erb

250x250 est, bien sûr, les dimensions, alors que # est la géométrie qui signifie "redimensionner et recadrer si nécessaire pour maintenir le rapport d'aspect avec la gravité centrale". Vous pouvez trouver des informations sur d'autres géométries sur le site Web de Dragonfly.

La méthode thumb est alimentée par ImageMagick—une excellente solution pour créer et manipuler des images. Par conséquent, afin de voir la démo de travail localement, vous aurez besoin d'installer ImageMagick (toutes les principales plates-formes sont pris en charge).

Le support pour ImageMagick est activé par défaut dans l'initialiseur de Dragonfly:

config/initializers/dragonfly.rb

Maintenant, les miniatures sont générées, mais elles ne sont stockées nulle part. Cela signifie que chaque fois qu'un utilisateur visite la page des albums, les vignettes seront régénérées. Il existe deux façons de surmonter ce problème: en les générant après l'enregistrement de l'enregistrement ou en exécutant la génération à la volée.

La première option implique l'introduction d'une nouvelle colonne pour stocker la vignette et de peaufiner la méthode dragonfly_accessor. Créez et appliquez une nouvelle migration:

Modifiez maintenant le modèle:

models/album.rb

Notez que maintenant le premier appel à dragonfly_accessor envoie un bloc qui génère réellement la vignette pour nous et le copie dans l'image_thumb. Maintenant, utilisez la méthode image_thumb dans vos vues:

views/albums/_album.html.erb

Cette solution est la plus simple, mais elle n'est pas recommandée par les documents officiels et, ce qui est pire, au moment de la rédaction, elle ne fonctionne pas avec les champs retained_*.

Par conséquent, permettez-moi de vous montrer une autre option: générer des vignettes à la volée. Il s'agit de créer un nouveau modèle et de peaufiner le fichier de configuration de Dragonfly. Tout d'abord, le modèle:

La table thumbs hébergera vos miniatures, mais elles seront générées à la demande. Pour que cela se produise, nous devons redéfinir la méthode url à l'intérieur de l'initialiseur Dragonfly:

config/initializers/dragonfly.rb

Ajoutez maintenant un nouvel album et visitez la page racine. La première fois que vous le faites, la sortie suivante sera imprimée dans les registres:

Cela signifie effectivement que la vignette est générée pour nous par ImageMagick. Si vous rechargez la page, cette ligne n'apparaîtra plus, ce qui signifie que la vignette a été mise en cache! Vous pouvez lire un peu plus sur cette fonctionnalité sur le site Web de Dragonfly.

Plus de traitement

Vous pouvez effectuer pratiquement n'importe quelle manipulation à vos images après qu'elles ont été téléchargées. Cela peut être fait à l'intérieur de la callback after_assign. Par exemple, convertissons toutes nos images au format JPEG avec 90% de qualité:

Il existe bien d'autres actions que vous pouvez effectuer: faire pivoter et recadrer les images, les encoder avec un format différent, écrire du texte sur elles, les mélanger avec d'autres images (par exemple, pour placer un filigrane), etc. Pour voir d'autres exemples, reportez-vous à la section ImageMagick du site Web de Dragonfly.

Téléchargement et gestion des chansons

Bien sûr, la partie principale de notre site musical est des chansons, alors ajoutons-les maintenant. Chaque chanson a un titre et un fichier musical, et il appartient à un album:

Raccordez les méthodes Dragonfly, comme nous l'avons fait pour le modèle Album:

models/song.rb

N'oubliez pas d'établir une relation has_many:

models/album.rb

Ajoutez des nouvelles routes. Une chanson existe toujours dans la portée d'un album, donc je vais faire les niches de ces routes:

config/routes.rb

Créez un contrôleur très simple (encore une fois, n'oubliez pas d'autoriser le champ de track):

songs_controller.rb

Affichez les morceaux et un lien pour en ajouter un nouveau:

views/albums/show.html.erb

Codez le formulaire:

views/songs/new.html.erb

Enfin, ajoutez le _song partiel:

views/songs/_song.html.erb

Ici, j'utilise la balise audio HTML5, qui ne fonctionnera pas pour les anciens navigateurs. Donc, si vous souhaitez soutenir de tels navigateurs, utilisez un polyfill.

Comme vous le voyez, tout le processus est très simple. Dragonfly ne se soucie pas vraiment quel type de fichier vous souhaitez télécharger; tout ce que vous devez faire est de fournir une méthode dragonfly_accessor, ajouter un champ approprié, le permettre et rendre une balise d'entrée de fichier.

Stockage des métadonnées

Quand j'ouvre une liste de lecture, je m'attends à voir des informations supplémentaires sur chaque chanson, comme sa durée ou son débit. Bien sûr, par défaut, cette information n'est pas stockée n'importe où, mais nous pouvons corriger cela très facilement. Dragonfly nous permet de fournir des données supplémentaires sur chaque fichier téléchargé et de les extraire plus tard en utilisant la meta méthode.

Cependant, les choses sont un peu plus complexes lorsque nous travaillons avec audio ou vidéo, car pour extraire leurs métadonnées, un joyau spécial streamio-ffmpeg est nécessaire. Ce joyau, à son tour, s'appuie sur FFmpeg, donc pour procéder, vous devrez l'installer sur votre PC.

Ajoutez streamio-ffmpeg dans le Gemfile:

Gemfile

Installez-le:

Maintenant nous pouvons employer le même rappel de after_assign déjà vu dans les sections précédentes:

models/song.rb

Notez que ici je suis en train d'utiliser une méthode de path, pas url, parce qu'à ce stade, nous travaillons avec un fichier temporaire. Ensuite, il suffit d'extraire la durée de la chanson (en la transformant en minutes et en secondes avec des zéros en tête) et son débit (le convertir en kilo bytes par seconde).

Enfin, affichez les métadonnées dans la vue:

views/songs/_song.html.erb

Si vous vérifiez le contenu sur le dossier public/system/dragonfly (l'emplacement par défaut pour héberger les téléchargements), vous noterez certains fichiers .yml—ils stockent toutes les métadonnées au format YAML.

Déploiement à Heroku

Le dernier sujet que nous aborderons aujourd'hui est de savoir comment préparer votre application avant de la déployer sur la plate-forme cloud Heroku. Le principal problème est que Heroku ne vous permet pas de stocker des fichiers personnalisés (comme les téléchargements), donc nous devons compter sur un service de stockage en nuage comme Amazon S3. Heureusement, Dragonfly peut être intégré facilement.

Tout ce que vous devez faire est d'enregistrer un nouveau compte chez AWS (si vous ne l'avez pas déjà), de créer un utilisateur avec la permission d'accéder aux seaux S3 et d'écrire la paire de clés de l'utilisateur dans un endroit sûr. Vous pouvez utiliser une paire de clés racine, mais ce n'est vraiment pas recommandé. Enfin, créez un seau S3.

Pour en revenir à notre application Rails, déposez un nouveau joyau:

Gemfile

Installez-le:

Puis ajustez la configuration de Dragonfly pour utiliser S3 dans un environnement de production:

config/initializers/dragonfly.rb

Pour fournir des variables ENV sur Heroku, utilisez cette commande:

Si vous souhaitez tester l'intégration avec S3 localement, vous pouvez utiliser une gemme comme dotenv-rails pour gérer les variables d'environnement. N'oubliez pas toutefois que votre paire de clés AWS ne doit pas être exposée au public!

Un autre petit problème que j'ai rencontré lors du déploiement à Heroku était l'absence de FFmpeg. La chose est que lorsqu'une nouvelle application Heroku est en cours de création, elle a un ensemble de services qui sont couramment utilisés (par exemple, ImageMagick est disponible par défaut). D'autres services peuvent être installés sous forme d'ajouts Heroku ou sous forme de buildpack. Pour ajouter un buildpack FFmpeg, exécutez la commande suivante:

Maintenant tout est prêt, et vous pouvez partager votre application musicale avec le monde!

Conclusion

C'était un long voyage, n'est-ce pas? Aujourd'hui, nous avons discuté de Dragonfly—une solution pour le téléchargement de fichiers dans Rails. Nous avons vu sa configuration de base, certaines options de configuration, la génération de vignettes, le traitement et le stockage des métadonnées. De plus, nous avons intégré Dragonfly au service Amazon S3 et préparé notre application pour le déploiement en production.

Bien sûr, nous n'avons pas discuté tous les aspects de Dragonfly dans cet article, alors assurez-vous de parcourir son site officiel pour trouver une documentation complète et des exemples utiles. Si vous avez d'autres questions ou êtes coincé avec quelques exemples de code, n'hésitez pas à me contacter.

Merci de rester avec moi, et à bientôt!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.