with que node multiple files javascript node.js express multipart multer

javascript - que - upload files with multer



Multer crea nueva carpeta con datos (3)

Trataré de responder tu pregunta con un ejemplo de la vida real, al menos podrías aprender algo de ella. Si desea eliminar todo, excepto la carga más reciente, debe codificar algún tipo de lógica para diferenciar entre qué carga es reciente y cuáles son antiguas. A continuación describo, cómo resolvería este problema, podría no ser perfecto, pero así es como lo hago.

La carpeta nunca se eliminará automáticamente, a menos que la elimines de forma manual o programática.

El tamaño de la carpeta con 100 llamadas, asumiendo que en cada llamada que cargue un archivo de tamaño x será x multiplicado por 100

No desea limitar la carga de archivos, no suministre configuraciones de límites, sin embargo, se recomienda especificar un límite de carga de archivos.

Obviamente, puede adjuntar el multer a la aplicación o crear una instancia de la misma y pasarla a una ruta. Prefiero el segundo método:

configuración multer

var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, ''uploads/'') }, filename: function (req, file, cb) { var filename = file.originalname; var fileExtension = filename.split(".")[1]; cb(null, Date.now() + "." + fileExtension); } });

Como se muestra arriba, no permito que multer dé un nombre aleatorio al archivo cargado. Lo que hago es obtener el nombre del archivo, quitar su extensión y luego usar Date.now() que me dará la marca de tiempo actual añadida con la extensión del archivo cargado. Si hago seis subidas, se mostrarían de la siguiente manera (la mayoría de mis subidas fueron .jpg, tomadas del nombre de archivo).

Cómo terminaría la carga (las marcas de tiempo diferirían)

1453414099665.jpg (oldest) 1453414746114.JPG 1453414748991.jpg 1453414751662.jpg 1453414754815.jpg (most recent)

Adjunté el storage anterior a una instancia de multer de la siguiente manera:

var upload = multer({storage: storage});

Ahora puedo pasar la upload a una ruta que maneje la carga del archivo de la siguiente manera:

adjuntar carga a la ruta como se muestra a continuación

//simple route to return upload form, simple jade file app.get(''/upload'', function(req, res){ res.render(''upload''); }); //this route processes the upload request, see below upload.single(''file'') //is the passed multer app.post(''/upload'', upload.single(''file''), function(req,res){ res.status(204).end(); });

Digamos que sigue subiendo y luego, en algún momento, desea enumerar todos los archivos en el directorio de subidas. La ruta sería la siguiente:

Listar todos los archivos en el directorio de subidas

//lists all files in the uploads directory and return it to browser as json response app.get(''/listAllFiles'', function(req, res) { //reading directory in synchronous way var files = fs.readdirSync(''./uploads''); res.json(files); });

Desea eliminar todos los archivos en el directorio de carga, la ruta se vería como sigue:

Eliminar todos los archivos en el directorio de subidas

//delete all files in the upload direcotry asynchronously app.get(''/deleteAllFiles'', function(req, res) { fs.readdir(''./uploads'', function(err, items) { items.forEach(function(file) { fs.unlink(''./uploads/'' + file); console.log(''Deleted '' + file); }); res.status(204).end(); }); });

Si desea eliminar todos los archivos de forma sincrónica, debe invocar la versión de sincronización de readdir (readdirSync) y desvincular (unlinkSync)

var filenames = fs.readdirSync(''./uploads''); filenames.forEach(function(file) { fs.unlinkSync(''./uploads/'' + file); });

Ahora a su punto de eliminar todo pero, el archivo cargado más reciente. Bueno, ya he hecho que todos los nombres de archivo sean marcas de tiempo. Así que haría algo como sigue:

Elimine todos los archivos excepto los más recientes (donde el más reciente es el que tiene la marca de tiempo más reciente como su nombre de archivo).

//delets all file asynchronously except the most recent in which case the file //with name being the latest timestamp is skipped. app.get(''/deleteAllExceptMostRecent'', function(req, res) { console.log(''/deleteAllFilesExceptMostRecent''); fs.readdir(''./uploads'', function(err, items) { //sort the array of files names in reverse, so we have most recent file on top items.reverse(); var flag = true; items.forEach(function(file) { //skip deletion of most recent file. if condition executed onces only. if(flag) { flag = false; } else { fs.unlink(''./uploads/'' + file); console.log(''Deleted '' + file); } }); }); res.status(204).end(); });

No he agregado ningún límite en mi ejemplo, pero se recomienda. El límite de tamaño de archivo predeterminado es infinito y si no lo incluye en un entorno prod, entonces será vulnerable a los ataques DoS como se indica en los comentarios.

Para que la operación de archivo anterior funcione debe cargar

var fs = require(''fs'');

Con respecto a su segundo punto, simplemente omita la propiedad de los límites y el límite predeterminado será infinito.

Para fines de demostración, he configurado lo anterior en una aplicación nodejs en funcionamiento, vea a continuación:

app.js

var express = require(''express''); var multer = require(''multer''); var bodyParser = require(''body-parser''); var path = require(''path''); var fs = require(''fs''); var app = new express(); app.use(bodyParser.json()); // view engine setup app.set(''views'', path.join(__dirname, ''views'')); app.set(''view engine'', ''jade''); var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, ''uploads/'') }, filename: function (req, file, cb) { /* if you need to retain the original filename, then use filename and append to it date * if you don''t need original filename but, just extension, then append extension at the * end of current timestamp. If you don''t need extenion then just use Date.now() which */ var filename = file.originalname; var fileExtension = filename.split(".")[1]; cb(null, Date.now() + "." + fileExtension); } }) var upload = multer({storage: storage}); //get upload form app.get(''/upload'', function(req, res){ res.render(''upload''); }); //process upload app.post(''/upload'', upload.single(''file''), function(req,res){ res.status(204).end(); }); //lists all files in the uploads directory. app.get(''/listAllFiles'', function(req, res) { var files = fs.readdirSync(''./uploads''); res.json(files); }); //delete all files in the upload direcotry asynchronously app.get(''/deleteAllFiles'', function(req, res) { fs.readdir(''./uploads'', function(err, items) { items.forEach(function(file) { fs.unlink(''./uploads/'' + file); console.log(''Deleted '' + file); }); res.status(204).end(); }); }); //delets all file asynchronously except the most recent in which case the file //with name being the latest timestamp is skipped. app.get(''/deleteAllExceptMostRecent'', function(req, res) { console.log(''/deleteAllFilesExceptMostRecent''); fs.readdir(''./uploads'', function(err, items) { items.reverse(); var flag = true; items.forEach(function(file) { if(flag) { flag = false; } else { fs.unlink(''./uploads/'' + file); console.log(''Deleted '' + file); } }); }); res.status(204).end(); }); //delete all files of a direcotry in synchronous way app.get(''/deleteAllSync'', function(req, res) { var filenames = fs.readdirSync(''./uploads''); filenames.forEach(function(file) { fs.unlinkSync(''./uploads/'' + file); }); }); //delete all files except most recent in synchronous way app.get(''/deleteAllSyncExceptMostRecent'', function(req, res) { var filenames = fs.readdirSync(''./uploads''); filenames.reverse(); var flag = true; filenames.forEach(function(file) { if(flag) flag = false; else fs.unlinkSync(''./uploads/'' + file); }); }); var port = 3000; app.listen( port, function(){ console.log(''listening on port ''+port); } );

vistas / subir.jade

html head title body form(method="post",enctype="multipart/form-data",action="/upload") p input(type="file",name="file") p input(type="submit")

Yo uso multer .

Pregunta 1

Cuando puse el siguiente fragmento de código en app.js

app.use(multer({ dest: ''./uploads'' } ).single(''file''));

crea una nueva carpeta en la carpeta raíz, mi pregunta es sobre el ciclo de vida de esta nueva carpeta, ¿Cuándo se eliminará? ¿Cuánto podría ser el tamaño de la carpeta después de 100 llamadas?

Pregunta 2

Si no quiero limitar el tamaño del archivo, ¿qué debo poner en la configuración?

app.use(multer({ dest: ''./public/profile/img/'', limits: { fieldNameSize: 50, files: 1, fields: 5, fileSize: 1024 * 1024 },

Actualizar

Mi aplicación está construida como

el archivo app.js contiene

app.use(multer({ dest: ''./uploads'' } ).single(''file'')); app.use(''/'', routes, function (req, res, next) { next(); });

El archivo de ruta se parece a los siguientes

appRouter .post(''*'', function (req, res) { handler.dispatch(req, res) }) .get(''*'', function (req, res) { handler.dispatch(req, res) })

Y en el tercer archivo utilizo el descomprimir como siguiente

update: function (req, res) { var filePath = path.join(req.file.destination, req.file.filename); var unzipper = new Unzipper(filePath); unzipper.on("extract", function () { console.log("Finished extracting"); res.sendStatus(200); }); unzipper.on(''progress'', function (fileIndex, fileCount) { console.log(''Extracted file '' + (fileIndex + 1) + '' of '' + fileCount); }); unzipper.on(''list'', function (files) { console.log(''The archive contains:''); console.log(files); }); unzipper.on(''error'', function (err) { console.log(''Caught an error'', err); }); unzipper.extract({ path: "./" }); }

A continuación se muestra cómo está estructurada mi aplicación de nodo. ¿Puede alguien recomendar cómo y dónde (qué archivo) se recomienda usar el código de Raf con la adición de una fecha y hora al archivo que puedo agregar clasificación ...


(1) Cuando realiza la siguiente llamada, le está diciendo a multer que coloque los archivos cargados en un directorio llamado uploads . Así que creará ese directorio para usted si aún no está presente cuando se inicie su aplicación.

app.use(multer({ dest: ''./uploads'' } ).single(''file''));

En términos del ciclo de vida de ese directorio, permanecerá allí mientras no lo elimines, y aún le estás pidiendo a Multer que lo use como destino. Los archivos cargados se agregan allí, por lo que el tamaño de su contenido depende de lo que se cargue.

(2) En cuanto a la limitación del tamaño del archivo, el valor predeterminado según los documentos es Infinito. Así que no hay límite a menos que establezca uno.

Pero, al no conocer su aplicación, todavía le sugiero que establezca un límite, incluso si necesita que sea bastante alto. Eliminar el límite de tamaño por completo puede llevar a grandes problemas.

editar
Si desea eliminar el contenido de ./uploads cuando se ./uploads un nuevo archivo, Node proporciona una forma de eliminar un archivo: fs.unlink . Véase también SO sobre la eliminación de un archivo en el nodo

En su controlador de carga, inspeccione el contenido de ./uploads y unlink cualquier archivo que no sea el archivo utilizado en la solicitud actual. Ver req.file para la carga actual.


Que 1) Puede decidir el ciclo de vida de las carpetas.

  1. Si desea almacenar archivos en el servidor y recuperarlos en cualquier momento sin límite de tamaño de archivo, necesita un mayor almacenamiento
  2. Si está utilizando un tercero como Amazon S3 para almacenar, no tiene sentido almacenarlo localmente, tan pronto como se cargue en el servidor, puede eliminarlo del almacenamiento local. Se puede usar después de Hook cuando se envía la respuesta.

    app.use(function (req, res, next) { function afterResponse() { res.removeListener(''finish'', afterRequest); res.removeListener(''close'', afterRequest); // Delete files from multer // you can delete older one from upload folder as you see new one came here. } res.on(''finish'', afterResponse); res.on(''close'', afterResponse); // action before request // eventually calling `next()` });

Que 2) Por defecto es ilimitado.