J'essaie de télécharger une vidéo volumineuse (8,3 Go) sur mon serveur Node.js (Express) en la segmentant à l'aide de busboy . Comment recevoir chaque morceau (busboy fait cette partie) et le reconstituer en une seule vidéo?
J'ai cherché des flux lisibles et inscriptibles, mais je ne reçois jamais la vidéo entière. J'en écrase certaines parties, ce qui fait environ 1 Go.
Voici mon code:
req.busboy.on('file', (fieldname, file, filename) => { logger.info(`Upload of '${filename}' started`); const video = fs.createReadStream(path.join(`${process.cwd()}/uploads`, filename)); const fstream = fs.createWriteStream(path.join(`${process.cwd()}/uploads`, filename)); if (video) { video.pipe(fstream); } file.pipe(fstream); fstream.on('close', () => { logger.info(`Upload of '${filename}' finished`); res.status(200).send(`Upload of '${filename}' finished`); }); });
4 Réponses :
Je pense que multer est bon avec ça, avez-vous essayé multer?
Oui, j'ai essayé multer. À ma connaissance, il ne gère pas la segmentation.
Utiliser les flux
multer vous permet de gérer facilement les téléchargements de fichiers dans le cadre d'un itinéraire express. Cela fonctionne très bien pour les petits fichiers qui ne laissent pas une empreinte mémoire importante.
Le problème avec le chargement d'un gros fichier en mémoire est que vous pouvez en fait manquer de mémoire et provoquer le blocage de votre application.
utilise une requête multipart / form-data. Cela peut être géré en attribuant le readStream à ce champ à la place dans vos options de requête
les flux sont extrêmement utiles pour optimiser les performances.
Essayez avec cet exemple de code, je pense que cela fonctionnera pour vous.
busboy.on("file", function(fieldName, file, filename, encoding, mimetype){ const writeStream = fs.createWriteStream(writePath); file.pipe(writeStream); file.on("data", data => { totalSize += data.length; cb(totalSize); }); file.on("end", () => { console.log("File "+ fieldName +" finished"); }); });
Vous pouvez également consulter ce lien pour résoudre ce problème
Après plus de 12 heures, je l'ai compris en utilisant des éléments de cet article qui m'a été donné . J'ai trouvé ce code:
//busboy is middleware on my index.js const fs = require('fs-extra'); const streamToBuffer = require('fast-stream-to-buffer'); //API function called first uploadVideoChunks(req, res) { req.pipe(req.busboy); req.busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { const fileNameBase = filename.replace(/\.[^/.]+$/, ''); //save all the chunks to a temp folder with .tmp extensions streamToBuffer(file, function (error, buffer) { const chunkDir = `${process.cwd()}/uploads/${fileNameBase}`; fs.outputFileSync(path.join(chunkDir, `${Date.now()}-${fileNameBase}.tmp`), buffer); }); }); req.busboy.on('finish', () => { res.status(200).send(`Finshed uploading chunk`); }); } //API function called once all chunks are uploaded saveToFile(req, res) { const { filename, profileId, movieId } = req.body; const uploadDir = `${process.cwd()}/uploads`; const fileNameBase = filename.replace(/\.[^/.]+$/, ''); const chunkDir = `${uploadDir}/${fileNameBase}`; let outputFile = fs.createWriteStream(path.join(uploadDir, filename)); fs.readdir(chunkDir, function(error, filenames) { if (error) { throw new Error('Cannot get upload chunks!'); } //loop through the temp dir and write to the stream to create a new file filenames.forEach(function(tempName) { const data = fs.readFileSync(`${chunkDir}/${tempName}`); outputFile.write(data); //delete the chunk we just handled fs.removeSync(`${chunkDir}/${tempName}`); }); outputFile.end(); }); outputFile.on('finish', async function () { //delete the temp folder once the file is written fs.removeSync(chunkDir); } }); }