web-dev-qa-db-ja.com

Multerがデータを含む新しいフォルダーを作成する

multer を使用します。

質問1

次のスニペットをapp.js

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

ルートフォルダーの下に新しいフォルダーを作成します。私の質問は、この新しいフォルダーのライフサイクルについてです。いつ削除されますか? 100回呼び出した後のフォルダのサイズはどのくらいですか?

質問2

ファイルサイズを制限したくない場合は、構成に何を入れればよいですか?

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

更新

私のアプリは

app.jsファイルには

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

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

ルートファイルは次のようになります

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

そして、3番目のファイルでは、次のように解凍を使用します

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

以下は私のノードアプリケーションの構造です、誰かがどのようにそしてどこに(どのファイル)そのがRafコードを使用してdateTimeを追加することを推奨するかをアドバイスできますか?ソートを追加できるファイルに...

25
user4209821

私は実際の例であなたの質問に答えようとします、少なくともあなたはそれから何かを学ぶかもしれません。最新のアップロード以外のすべてを削除する場合は、何らかのロジックをコーディングして、最近のアップロードと古いアップロードを区別する必要があります。以下では、この問題を解決する方法を説明しますが、完璧ではないかもしれませんが、それが私のやり方です。

手動またはプログラムで削除しない限り、フォルダーは自動的に削除されません。

各呼び出しでxサイズのファイルをアップロードするとxに100を掛けたものと想定して、100呼び出しのフォルダーのサイズ

ファイルのアップロードを制限したくない、limits configsを指定しない、ただしファイルのアップロード制限を指定することをお勧めします。

アプリに明らかにmulterをアタッチするか、そのインスタンスを作成してそれをルートに渡すことができます。私は2番目の方法を好みます:

マルチ構成

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

上記のように、アップロードされたファイルに無作為の名前を付けてはいけません。私がすることは、ファイル名を取得し、その拡張子を取り除いてから、Date.now()を使用します。これにより、アップロードされたファイル拡張子が付加された現在のタイムスタンプが得られます。 6つのアップロードを行うと、次のように表示されます(私のアップロードのほとんどは.jpgで、ファイル名から取得されます)。

アップロードがどのように終了するか(タイムスタンプが異なる)

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

上記のstorageを次のようにmulterのインスタンスに添付しました。

_var upload = multer({storage: storage});
_

これで、uploadを次のようにファイルのアップロードを処理するルートに渡すことができます。

アップロードを以下のようにルーティングに添付

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

アップロードを続けた後、ある時点でアップロードディレクトリ内のすべてのファイルを一覧表示したいとします。ルートは次のようになります。

アップロードディレクトリ内のすべてのファイルをリスト

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

アップロードディレクトリ内のすべてのファイルを削除する場合、ルートは次のようになります。

アップロードディレクトリ内のすべてのファイルを削除

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

すべてのファイルを同期的に削除したい場合は、readdir(readdirSync)とunlink(unlinkSync)の同期バージョンを呼び出す必要があります。

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

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

次に、最後にアップロードしたファイルを除くすべてを削除します。まあ、私はすでにすべてのファイル名をタイムスタンプにしています。だから私は次のように何かをします:

最新のものを除くすべてのファイルを削除します(最新のものは、ファイル名として最新のタイムスタンプを持つファイルです)。

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

この例では制限を追加していませんが、推奨されています。デフォルトのファイルサイズ制限は無限大であり、製品環境に含めないと、コメントに示されているようにDoS攻撃に対して脆弱になります。

上記のファイル操作が機能するには、ロードする必要があります

_var fs = require('fs'); 
_

2番目の点に関しては、limitsプロパティをスキップするだけで、デフォルトの制限は無限になります。

デモ目的で、私は上記を動作するnodejsアプリで設定しました。以下を参照してください:

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

views/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)次の呼び出しを行うと、アップロードされたファイルをuploadsというディレクトリに配置するようにmulterに指示します。そのため、アプリの起動時にまだ存在しない場合は、dirが作成されます。

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

そのディレクトリのライフサイクルに関しては、ディレクトリを削除しない限り存在し続け、それをマルチディレクトリに宛先として使用するように求めています。アップロードされたファイルはそこに追加されているので、コンテンツのサイズはアップロードされる内容によって異なります。

(2)ファイルサイズの制限については、ドキュメントによるデフォルトはInfinityです。したがって、設定しない限り制限はありません。

しかし、アプリケーションを知らないので、かなり高くする必要がある場合でも、制限を設定することを強くお勧めします。サイズ制限を完全に削除すると、大きな問題が発生する可能性があります。


edit
新しいファイルがアップロードされたときに./uploadsの内容を削除したい場合、Nodeはファイルを削除する方法を提供します: fs。 unlink 。参照 ノード内のファイルの削除に関するSO

アップロードハンドラーで、現在のリクエストで使用されているファイルではない./uploadsおよびunlinkのコンテンツを調べます。現在のアップロードについては、req.fileをご覧ください。

1
csum

Que 1)フォルダのライフサイクルを決定できます。

  1. ファイルをサーバーに保存し、ファイルサイズの制限なしでいつでも取得したい場合は、より大きなストレージが必要です。
  2. Amazon S3のようなサードパーティを使用して保存している場合、ローカルに保存しても意味がありません。サーバーにアップロードするとすぐに、ローカルストレージから削除できます。応答の送信時に フックの後で を使用できます。

    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)デフォルトは無制限です。

0
JagsSparrow