Multer 使用数据创建新文件夹

2024-06-01

I use multer https://github.com/expressjs/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
    },

Update

我的应用程序是这样构建的

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

在第三个文件中,我使用如下解压缩

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 代码向文件添加日期时间,我可以添加排序...


我会尝试用一个现实生活中的例子来回答你的问题,至少你可以从中学到一些东西。如果您希望删除除最近上传的所有内容,那么您需要编写某种逻辑来区分哪些上传是最近的,哪些是旧的。下面我描述了我将如何解决这个问题,可能并不完美,但我就是这样做的。

该文件夹永远不会自动删除,除非您手动或以编程方式删除它。

包含 100 个调用的文件夹的大小,假设在每次调用中您上传 x 大小的文件将是 x 乘以 100

您不想限制文件上传,请勿提供限制配置,但建议指定文件上传限制。

显然,您可以将 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);
  }
}); 

如上所示,我不让 multer 给上传的文件起一个随机名称。我所做的是,获取文件名,去掉其扩展名,然后使用Date.now()这将为我提供当前时间戳并附加上传的文件扩展名。如果我上传六个,它们将显示如下(我的大部分上传都是 .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);
});

您想删除上传目录中的所有文件,路线如下:

删除uploads目录下的所有文件

//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)和取消链接(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'); 

关于第二点,只需跳过限制属性,默认限制将为无穷大。

出于演示目的,我在工作的 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); } );

视图/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")
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Multer 使用数据创建新文件夹 的相关文章

随机推荐

  • 如何从 Lua 内部运行另一个脚本?

    我需要从另一个 Lua 脚本中执行一个 Lua 脚本 有多少种方法 我该如何使用它们 通常您会使用以下内容 dofile filename lua 但你可以通过以下方式做到这一点require 很好 例子 foo lua io write
  • sqlite 增量真空仅删除一个空闲页面

    我已将 sqlite 数据库的 auto vacuum PRAGMA 值更改为 INCRMENTAL 当我跑步时PRAGMA incremental vacuum 通过 DB Browser for SQlite 应用程序 它释放了free
  • 如何在 Visual Studio 中调试时强制异常?

    我正在调试模式下运行我的应用程序 并且我想手动抛出异常 即不是从代码内部抛出异常 有什么办法可以做到这一点吗 当然 跑步throw new Exception My forced exception 在命令或立即窗口中不起作用 编辑 我希望
  • Android studio 3.1.4 - 无法下载示例索引(尝试下载谷歌代码示例时)

    我已经在 Windows 10 机器和 Ubuntu 18 04 上尝试了最新版本的 Android studio 但我无法下载 Google 代码示例 该错误指出 无法下载示例索引 请检查您的连接并重试 针对 2015 年此问题的早期实例
  • 当我的模型为空时,如何避免视图内的 foreach 循环中出现 NullReferenceException?

    当我通过控制器传入 null 值时 我的视图中收到以下代码的 NullReferenceException 未由用户代码处理 错误 在某些情况下 我想传入 null 值 但我不希望发生这种情况时引发错误 我应该将我的代码更改为什么 最初我的
  • 在 Java 中使用 Zip 和 GZip 文件

    我已经有一段时间没有完成 Java I O 了 而且我不知道使用 Zip 和 GZip 文件的最新 正确 方法 我不一定需要完整的工作演示 我主要是寻找要使用的正确接口和方法 是的 我可以查找任何关于此的随机教程 但性能是一个问题 这些文件
  • 同一文件的多个文件句柄

    So 这个问题 https stackoverflow com questions 23156116 pypy file append mode让我思考 我对同一个文件的多个文件句柄进行了一些测试 发现了一些奇怪的结果 我希望有人能解释一下
  • 如何区分设备进入 Doze 维护时段和退出 Doze 维护时段

    我有一个定期运行以保持网络连接活动的方法 在打瞌睡模式期间 我想禁止它定期运行 并在维护窗口期间只运行一次 当设备退出打瞌睡状态时 我希望再次定期调用该方法 我怎样才能做到这一点 我已经注册了一个接收器来监听PowerManager ACT
  • setf中的f代表什么?

    LISP 有setf函数给变量赋值 现在我一直想知道该函数的名称 Theset部分是显而易见的 但是什么是f后缀代表 F的实际含义经常被忘记 根据一些消息来源 f 后缀可以代表 字段 例如参见这个answer https stackover
  • BASH 中带有千位分隔符的数字格式

    我有一个号码12343423455 23353 我想用千位分隔符格式化数字 所以输出将是12 343 423 455 23353 printf 3f n 12345678 901 12 345 678 901
  • 为什么 pandas.series.map 如此慢?

    有时我只是讨厌使用中间件 以此为例 我想要一个查找表 将一组输入 域 值映射到输出 范围 值 映射是唯一的 Python 地图可以做到这一点 但由于地图相当大 我想为什么不使用 ps Series 及其索引 这给我带来了额外的好处 传入要映
  • 如何拥有程序执行时间的控制台?

    我正在尝试编写一个在控制台或 GUI 模式下工作的程序 具体取决于执行参数 我已经成功编写了以下示例代码 using System using System Collections Generic using System Linq usi
  • 当鼠标悬停在绝对 div 上时 jQuery 禁用滚动

    当鼠标悬停在 div 上时 我试图禁用窗口鼠标滚动功能 以便仅启用 div 滚动 当鼠标移离 div 时 再次应用滚动到窗口 div 是绝对定位的 我看过这个帖子当鼠标光标位于div内时 使用jquery禁用鼠标滚轮功能 https sta
  • 将模式的所有元素与向量以相同的顺序匹配

    我创建了一个函数yes seq需要两个参数 一个模式pat和数据dat 该函数以相同的顺序查找数据中是否存在模式 例如 dat lt letters 1 10 dat 1 a b c d e f g h i j pat lt c a c g
  • PowerShell设置文件夹权限

    我正在尝试使用 默认 选项来应用文件夹权限 我的意思是在文件夹的 属性 中使用 完全控制 写入 读取等 以下脚本用于添加用户 但它应用 特殊权限 而不是带有文件夹属性菜单中可见的复选框的权限 Acl Get Acl R9N2WRN Shar
  • 如何将体积补丁存储到 HDF5 中?

    我有一个尺寸的体积数据256x128x256 由于内存有限 我无法将整个数据直接输入到 CAFFE 因此 我会随机选择n sample补丁50x50x50从体积数据中提取并将其存储到 HDF5 中 我成功地从原始数据及其标签中随机提取了补丁
  • 未捕获的类型错误:无法读取 null 的属性“getElementsByTagName”

    我正在尝试选择元素 getElementsByTagName var tags document body getElementsByTagName 当前尝试使用从现有答案中吸取的经验教训https stackoverflow com qu
  • 在 python 2 或 python 3 中编写 csv 文件的便携式方法

    在我的 Windows 机器上 我通常在 python 2 中这样做来编写 csv 文件 import csv f open out csv wb cr csv writer f delimiter cr writerow a b c f
  • 我如何通过 Spring Security 创建 oauth 2 用户名密码流

    我正在尝试在 Spring Security 上实现 oauth2 用户名密码流程 但我找不到任何文档和示例代码 我正在检查 Sparklr 和 tonr insode oauth2 样本 我怎样才能实现它 oauth2 2 条腿 我如何禁
  • Multer 使用数据创建新文件夹

    I use multer https github com expressjs multer 问题1 当我将以下代码片段放入app js app use multer dest uploads single file 它在根文件夹下创建一个