Auparavant, un seul téléchargement de fichier était configuré et fonctionnait correctement. Maintenant, je dois lui faire gérer plusieurs fichiers.
Voici mon code en ce moment:
function sendUploadToGCS (req, res, next) { if (!req.file) { return next(); } const gcsname = Date.now() + req.file.originalname; const file = bucket.file(gcsname); const stream = file.createWriteStream({ metadata: { contentType: req.file.mimetype }, resumable: false }); stream.on('error', (err) => { req.file.cloudStorageError = err; next(err); }); stream.on('finish', () => { req.file.cloudStorageObject = gcsname; file.makePublic().then(() => { req.file.cloudStoragePublicUrl = getPublicUrl(gcsname); next(); }); }); stream.end(req.file.buffer); }
req.files me donne un tableau de fichiers, avec un tampon et une taille qui a du sens. Les promesses se résolvent toutes. Mais une fois que j'ai vérifié les fichiers dans le bucket google, ils ont le bon nom mais n'ont pas de contenu (et une taille de 0)
Comme je l'ai déjà dit, cela fonctionnait quand je le faisais avec un fichier (en utilisant m.single ('file')
Je ne veux pas utiliser le bucket comme destination avec la configuration de multer, car je dois également changer le nom du fichier avant de le télécharger dans google bucket.
edit: c'est l'exemple de code donné par les documentations google cloud pour les téléchargements de fichiers uniques ( https://cloud.google.com/nodejs/getting-started/using-cloud-storage ):
const multer = require('multer') const { Storage } = require('@google-cloud/storage') const storage = new Storage() const m = multer({ storage: multer.memoryStorage() }) module.exports = app => { app.use('/', router) router.post( '/reader-:shortId/file-upload', passport.authenticate('jwt', { session: false }), m.array('files'), async function (req, res) { const bucketName = req.params.shortId.toLowerCase() await storage.createBucket(bucketName) bucket = storage.bucket(bucketName) let promises = [] req.files.forEach((file) => { const blob = bucket.file(file.originalname) const newPromise = new Promise((resolve, reject) => { blob.createWriteStream({ metadata: { contentType: file.mimetype } }).on('finish', async response => { await blob.makePublic() resolve(response) }).on('error', err => { reject('upload error: ', err) }).end() }) promises.push(newPromise) }) Promise.all(promises).then((response) => { // the response I get here is [undefined, undefined] res.status(200).send(response) }).catch((err) => { res.status(400).send(err.message) }); }) }
I À l'origine, quelque chose comme ça fonctionnait, mais je ne comprends tout simplement pas d'où proviennent les données du tampon de fichier. C'est probablement là que les choses sont différentes avec plusieurs fichiers.
3 Réponses :
Ok, il s'est avéré que j'ai dû changer
.end ()
à
.end(file.buffer)
Je sais qu'il est trop tard, mais quelqu'un pourrait chercher une réponse pour importer plusieurs fichiers sur Google Cloud Storage.
Dépendances:
Voici le code du contrôleur.
exports.post_image_upload = async (req, res) => { /** Check if file exist */ if (!req.files) { res.status(400).send('No file uploaded.'); return; } let PublicUrls = [] req.files.forEach((file) => { const blob = bucket.file(file.fieldname + '-' + Date.now() + path.extname(file.originalname)) const blobStream = blob.createWriteStream({ metadata: { contentType: file.mimetype } }) blobStream.on('finish', ()=> { blob.makePublic() }) blobStream.on('error', err => { //Put your error message here }) blobStream.end(file.buffer) const Url = `https://storage.googleapis.com/${bucket.name}/${blob.name}` PublicUrls.push(Url) }) res.send(PublicUrls) }
Bonne chance
Marie Pelletier, je pense que votre approche est à 100% juste. J'ai modifié un peu votre code en essayant d'éviter la réponse asynchrone:
let promises = [] req.files.forEach((file) => { const blob = bucket.file(file.originalname) const newPromise = new Promise((resolve, reject) => { blob.createWriteStream({ metadata: { contentType: file.mimetype }, resumable: false //Good for small files }).on('finish', () => { const Url = `https://storage.googleapis.com/${bucket.name}/${blob.name}`; resolve({ name: file.originalname, url: Url }); }).on('error', err => { reject('upload error: ', err); }).end(file.buffer); }) promises.push(newPromise); }) Promise.all(promises).then((response) => { res.status(200).send(response) }).catch((err) => { res.status(400).send(err.message) });
De cette façon, je ne suis plus "indéfini".
Je ne vois pas où vous écrivez réellement le contenu du
fichier
. Les seules propriétés dufichier
que je vois en cours d'utilisation sontoriginalname
etmimetype
.