web-dev-qa-db-fra.com

Multer crée un nouveau dossier avec des données

J'utilise multer .

Question 1

Lorsque je mets l'extrait suivant dans le app.js

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

il crée un nouveau dossier sous le dossier racine, ma question concerne le cycle de vie de ce nouveau dossier, quand il sera supprimé? Quelle pourrait être la taille du dossier après 100 appels?

Question 2

Si je ne veux pas limiter la taille du fichier, que dois-je mettre dans la configuration?

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

Mise à jour

Mon application est construite comme

le fichier app.js contient

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

app.use('/', routes, function (req, res, next) {
    next();
});

Le fichier d'itinéraire ressemble à ce qui suit

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

Et dans le troisième fichier, j'utilise la décompression comme suit

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: "./"
            });
        }

Ce qui suit est la structure de mon application de nœud, quelqu'un peut-il s'il vous plaît conseiller comment et où (quel fichier) il est recommandé d'utiliser le code Raf avec l'ajout d'un dateTime au fichier auquel je peux ajouter le tri ...

25
user4209821

Je vais essayer de répondre à votre question avec un exemple concret, au moins vous pourriez en apprendre des choses. Si vous souhaitez tout supprimer à l'exception du téléchargement le plus récent, vous devez coder une sorte de logique pour différencier le téléchargement le plus récent et le plus ancien. Ci-dessous, je décris comment je pourrais résoudre ce problème n'est peut-être pas parfait, mais c'est ainsi que je le fais.

Le dossier ne sera jamais supprimé automatiquement, sauf si vous le supprimez manuellement ou par programme.

La taille du dossier avec 100 appels en supposant que dans chaque appel vous téléchargez un fichier de taille x serait x multiplié par 100

Vous ne voulez pas limiter le téléchargement de fichiers, ne fournissez pas de configurations de limites, mais il est recommandé de spécifier une limite de téléchargement de fichiers.

Vous pouvez évidemment attacher le multer à l'application ou en créer une instance et la transmettre à un itinéraire. Je préfère la deuxième méthode:

configuration du 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);
  }
}); 

Comme indiqué ci-dessus, je ne laisse pas le multer donner un nom aléatoire au fichier téléchargé. Ce que je fais est d'obtenir le nom du fichier, de retirer son extension puis d'utiliser Date.now() qui me donnera l'horodatage actuel ajouté avec l'extension de fichier téléchargée. Si je fais six téléchargements, ils s'afficheraient comme suit (la plupart de mes téléchargements étaient .jpg, qui sont tirés du nom de fichier).

Comment le téléchargement finirait (les horodatages différeraient)

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

J'ai attaché le storage ci-dessus à une instance de multer comme suit:

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

Maintenant, je peux passer le upload à une route qui gère le téléchargement du fichier comme suit:

joindre le téléchargement à l'itinéraire comme indiqué ci-dessous

//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();
});

Supposons que vous continuiez à télécharger et que vous souhaitiez à un moment donné répertorier tous les fichiers dans le répertoire de téléchargement. L'itinéraire serait le suivant:

Liste tous les fichiers dans le répertoire de téléchargement

//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);
});

Vous souhaitez supprimer tous les fichiers du répertoire de téléchargement, l'itinéraire ressemblerait à ceci:

Supprimer tous les fichiers du répertoire de téléchargement

//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 vous souhaitez supprimer tous les fichiers de manière synchrone, vous devez invoquer la version de synchronisation de readdir (readdirSync) et unlink (unlinkSync)

var filenames = fs.readdirSync('./uploads');

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

Maintenant à votre point de supprimer tous les fichiers téléchargés, à l'exception du plus récent. Eh bien, j'ai déjà fait que tous les noms de fichiers soient des horodatages. Je ferais donc quelque chose comme suit:

Supprimez tous les fichiers sauf le plus récent (où le plus récent est celui avec l'horodatage le plus récent comme nom de fichier).

//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();
});

Je n'ai ajouté aucune limite dans mon exemple mais, il est recommandé. La limite de taille de fichier par défaut est l'infini et si vous ne l'incluez pas dans un environnement de production, vous serez vulnérable aux attaques DoS, comme indiqué dans les commentaires.

Pour que l'opération de fichier ci-dessus fonctionne, vous devez charger

var fs = require('fs'); 

En ce qui concerne votre deuxième point, ignorez simplement la propriété limites et la limite par défaut sera l'infini.

À des fins de démonstration, j'ai configuré ce qui précède dans une application nodejs fonctionnelle, voir ci-dessous:

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); } );

vues/upload.jade

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

(1) Lorsque vous effectuez l'appel suivant, vous dites à multer de placer les fichiers téléchargés dans un répertoire appelé uploads. Il créera donc ce répertoire pour vous s'il n'est pas déjà présent au démarrage de votre application.

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

En termes de cycle de vie de ce répertoire, il y restera tant que vous ne le supprimerez pas et demandera toujours à multer de l'utiliser comme destination. Les fichiers téléchargés y sont ajoutés, donc la taille de son contenu dépend de ce qui est téléchargé.

(2) Quant à la limitation de la taille du fichier, la valeur par défaut selon les documents est Infinity. Il n'y a donc pas de limite sauf si vous en définissez une.

Mais, ne connaissant pas votre application, je vous suggère tout de même de fixer une limite, même si vous avez besoin qu'elle soit assez élevée. La suppression totale de la taille limite peut entraîner de gros problèmes.


modifier
Si vous souhaitez supprimer le contenu de ./uploads lorsqu'un nouveau fichier est téléchargé, Node fournit un moyen de supprimer un fichier: fs.unlink . Voir aussi SO sur la suppression d'un fichier dans nœud

Dans votre gestionnaire de téléchargement, inspectez le contenu de ./uploads et unlink tout fichier qui n'est pas le fichier utilisé dans la demande en cours. Voir req.file pour le téléchargement en cours.

1
csum

Que 1) Vous pouvez décider du cycle de vie des dossiers.

  1. Si vous souhaitez stocker des fichiers sur le serveur et les récupérer à tout moment sans limite de taille de fichier, vous avez besoin d'un stockage plus important
  2. Si vous utilisez un tiers comme Amazon S3 pour stocker, inutile de stocker localement, dès qu'il est téléchargé sur le serveur, vous pouvez le supprimer du stockage local. Vous pouvez utiliser après le crochet lorsque la réponse est envoyée.

    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) La valeur par défaut est illimitée.

0
JagsSparrow