Express 09.1 - đ Upload de fichier (back)
Comment apprĂ©hender la quĂȘte ?
Ensemble, nous allons créer un systÚme pour la réception d'image depuis un frontend. Comment ça va se passer ?
Je vais vous guider pour la bonne gestion de cette quĂȘte, mais en Ă©change, je souhaite que vous fassiez votre propre recherche, que ce soit Google ou collĂšgues, peu importe, tant que vous faites l'effort de chercher ! On va faire un tour sur des documentations, comprendre pourquoi on les utilise et Ă la fin, avoir notre image qui s'upload :tada:
Alors, vous ĂȘtes prĂȘt ?!
Installation de Multer
Pour la suite de la quĂȘte, je me suis basĂ© sur ce repo que vous pouvez fork puis clone.
Commencez par lire les fichiers README (tous : dans le répertoire racine et dans les sous-dossiers frontend et backend), et recherchez la commande pour setup le projet.
Afficher la solution|||javascript|||Tu as des doutes sur comment faire ?|||0|||Masquer
npm install
Vous pouvez Ă©galement crĂ©er la base de donnĂ©es avec npm run migrate (aprĂšs avoir créé le fichier .env adĂ©quat), mais cela ne sera pas nĂ©cessaire pour cette quĂȘte.
Nous allons commencer par installer le package multer dans notre dossier backend, nous verrons aprĂšs pourquoi on utilise multer !
Afficher la solution|||bash|||On installe un package dans le dossier backend|||0|||Masquer
cd nom_de_votre_projet/backend
npm install multer
Nous pouvons voir que le package.json s'est mis Ă jour avec multer !
Mise en place de Multer
Nous allons nous intéresser au fichier router.js de notre dossier src
// ./src/router.js
const express = require("express");
// Ajout de multer
const multer = require("multer");
// du code
Comment fonctionne multer ?
Si on se rĂ©fĂšre Ă la documentation de multer, on peut voir que multer est un middleware qui va nous permettre de gĂ©rer les fichiers entrants dans nos requĂȘtes HTTP.
Pour ce faire, j'ai besoin d'un dossier de destination oĂč je vais stocker mes fichiers. Pour cela, je vais crĂ©er une constante upload et grĂące Ă multer je vais dĂ©finir ma destination ./public/upload.
# Création du dossier de destination
# Dans notre cas, nous allons le créer dans le dossier backend/public, n'oubliez pas de vous y rendre !
mkdir uploads
Afficher la solution|||javascript|||Tu as des doutes sur comment faire ?|||0|||Masquer
// ./src/router.js
const express = require("express");
// Ajout de multer
const multer = require("multer");
// On définit la destination de stockage de nos fichiers
const upload = multer({ dest: "./public/uploads/" });
// du code...
Mais pourquoi faire ça ? Dans le dossier public ?
Car dans app.js, nous avons ça
// Serve the public folder for public resources
app.use(express.static(path.join(__dirname, "../public")));
express.static ouvre le dossier à tout le monde, ça tombe bien, parce que nous avons nos futures images dedans, c'est top !
Du coup, coté front, on pourra accéder à nos images de cette maniÚre ${BACKEND_URL}/${nomDuFichier}, mais ça, c'est pour plus tard :wink:
Ma 1Êłá” route
Nous allons créer notre premiÚre route POST qui va nous permettre de recevoir un fichier.
N'hésitez pas à suivre la documentation :wink:
Afficher la solution|||javascript|||Tu as des doutes sur comment faire ?|||0|||Masquer
// ./src/router.js
const express = require("express");
// Ajout de multer
const multer = require("multer");
// On définit la destination de stockage de nos fichiers
const upload = multer({ dest: "./public/uploads/" });
// route POST pour recevoir un fichier dont le nom est "avatar"
router.post("/api/avatar", upload.single("avatar"), (req, res) => {
res.send("File uploaded");
});
Je vous laisse tester maintenant !
# Lancement du serveur
npm run dev-back
Si vous souhaitez utiliser postman, insomnia ou autre et que vous ne savez pas comment faire pour envoyer une image, je vous invite Ă faire comme moi ! Une petite recherche Google :smile: Car il est possible qu'entre le temps oĂč j'ai Ă©crit cette quĂȘte et le moment oĂč vous lĂ lisez, les applications aient changĂ©. MĂȘme si on met Ă jour la quĂȘte rĂ©guliĂšrement, il y a toujours un risque que ça change.
Tiens, voilà la phrase que j'ai écrite|||text|||Tu n'as pas encore trouvé ? N'hésite pas à continuer tes recherches|||0|||Masquer
Recherche:
> How to upload a file with {postman/insomnia}:
Réponses :
- Postman: https://youtu.be/S7bwkys6D0E
- Insomnia: https://stackoverflow.com/questions/44365061/insomnia-upload-pic-and-post-data-at-same-time
Dans mon cas, j'ai utilisé insomnia et j'ai pu envoyer mon fichier avec succÚs !
J'ai bien reçu mon fichier dans mon dossier uploads, le problÚme, c'est que le nom de mon fichier ressemble à ça : 108b2ec2fbbb61f03740061a69ab7c36. Et vous ? :yum:
C'est normal, c'est le nom que nous a donné multer. Mais nous, on veut un nom plus parlant, non ?
Comment faire pour avoir un nom de fichier plus parlant ?
Pour cela, nous allons utiliser la fonction rename de fs (file system) de node.js, voir ici (attention, ne pas oublier de le `require` comme tous les autres packages que nous avons utilisés jusqu'à présent :muscle: ).
Ta mission, si tu l'acceptes, c'est de renommer le fichier avec le nom d'origine.
Comment faire ? N'oublie pas d'utiliser la documentation de multer pour t'aider :wink:
Afficher|||text|||1er indice|||0|||Masquer
Tu peux essayer de `console.log(req)`, et si tu veux aller plus loin, tu peux `console.log(req.file)` !
Afficher|||js|||2eme indice|||0|||Masquer
console.log(req.file)
// output âŹïž
{
fieldname: 'avatar',
originalname: 'mon_avatar.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'uploads/',
filename: '58a8cce161de344cf73babe3336eb762',
path: 'uploads/58a8cce161de344cf73babe3336eb762',
size: 731934
}
Afficher la solution|||javascript|||Attend, tu as vraiment tout essayé ?|||0|||Masquer
// ./src/router.js
const express = require("express");
const fs = require("fs");
// Ajout de multer
const multer = require("multer");
// On définit la destination de stockage de nos fichiers
const upload = multer({ dest: "./public/uploads/" });
// route POST pour recevoir un fichier
router.post("/api/avatar", upload.single("avatar"), (req, res) => {
// On récupÚre le nom du fichier
const { originalname } = req.file;
// On récupÚre le nom du fichier
const { filename } = req.file;
// On utilise la fonction rename de fs pour renommer le fichier
fs
.rename(`./public/uploads/${filename}`, `./public/uploads/${originalname}`, (err) => {
if (err) throw err;
res.send("File uploaded");
});
});
Alors, ça fonctionne ?
Si oui, bravo ! :tada:
Alors, nous allons faire un test supplémentaire ! Par exemple, nous allons envoyer un fichier avec un nom qui existe déjà dans notre dossier uploads et voir ce qui se passe.
Oui|||text|||Tu as essayé ?|||0|||Masquer
Ăa ne va pas fonctionner, je le sais dĂ©jĂ :wink:
Pourquoi ça ne fonctionne pas ? En faite, ça fonctionne, mais il Ă©crase l'ancienne image qui porte le mĂȘme nom !
Ce que nous devons faire, c'est ajouter un élément à notre nom de fichier pour qu'il soit unique.
Pour cela, nous allons utiliser la fonction uuid de uuid (oui, c'est un peu bizarre comme nom :smile:)
# Installation de uuid
npm i uuid
Afficher la solution|||javascript|||Tu as des doutes sur comment faire ?|||0|||Masquer
// ./src/router.js
const express = require("express");
const fs = require("fs");
// Ajout de multer
const multer = require("multer");
// Ajout de uuid
const { v4: uuidv4 } = require("uuid");
// On définit la destination de stockage de nos fichiers
const upload = multer({ dest: "uploads/" });
// route POST pour recevoir un fichier
router.post("/api/avatar", upload.single("avatar"), (req, res) => {
// On récupÚre le nom du fichier
const { originalname } = req.file;
// On récupÚre le nom du fichier
const { filename } = req.file;
// On utilise la fonction rename de fs pour renommer le fichier
fs
.rename(`./public/uploads/${filename}`, `./public/uploads/${uuidv4()}-${originalname}`, (err) => {
if (err) throw err;
res.send("File uploaded");
});
});
Et maintenant ?
Si vous avez bien suivi, vous devriez avoir un fichier qui s'appelle public/uploads/4db44163-0810-441b-9d97-8fd0ac09e085-mon_avatar.png.
Conseil : il est important de conserver le nom de l'image original. Cela laisse la possibilité d'optimiser le SEO par les administrateurs. Dans ce cas, les noms d'images doivent comporter des '-', pas d'espace ni '_'.
Et voilĂ !
Ressources partagĂ©es sur cette quĂȘte
- Pour uploader des fichiers avec Postmanhttps://learning.postman.com/docs/sending-requests/requests/#form-data
- si vous avez des erreurs et pour éviter de chercher durant des heures ;-)https://maximorlov.com/fix-unexpected-field-error-multer/