expressionfile upload错误和几个问题

我正在使用多方处理file upload。

在我的控制器中,我有

exports.uploadFile = function(req, res, next) { if (req.files && req.files.file) { var file = req.files.file var tmpPath = file.path var targetDirectory = dir.public + '/upload' var targetPath = dir.public + '/upload' + '/' + file.name if (file.size > config.uploadFileMaxSize) { fs.unlink(tmpPath, function(err) { if (err) return next(err) return next(helper.getAbuseError('file is too large')) }) } else { fs.mkdir(targetDirectory, function(err) { if (err && err.code !== 'EEXIST') return next(err) fs.rename(tmpPath, targetPath, function(err) { if (err) return next(err) fs.unlink(tmpPath, function(err) { if (err) return next(err) return res.json(helper.dataAppendedWithMessage({path: targetPath}, 'success', 'file uploaded')) }) }) }) } } } 

在我的路由器中:

 restRouter.post(helper.serverUrl.common.uploadFile, helper.permission.middleware(helper.accessList.uploadFile), multiparty(), //Note: only used in file uploads commonController.uploadFile) 

有几个问题。

  1. 无法mkdir。 错误在断开连接

    ENOENT,unlink'/var/folders/5p/qqz2vyhd3yqb_334h6fj7_y00000gq/T/O3BTOo3rXdKRT3Zfs5JPUpn8.png'

  2. 为什么上面的/var/folders下的tmpPath? 从我读的所有教程中,它应该存储在[app_root]/tmp

  3. 除了检查文件大小,我怎么只允许图像,audio和video? 我需要支持所有可以embedded和标记的types,并拒绝其他所有的types。 我知道有一个file.type值,但我不想硬编码。 我如何检查文件types是否可以在HTML5标签中使用?

  4. 在我的成功callback中,我发回{path: targetPath}供客户端标记使用。 但是targetPath是/path/to/app_root/public/upload/xxx.png ,我怎么才能发回/public/upload/xxx.png ? 我当然可以searchpublic和剥离/path/to/app_root/但代码会变得混乱。 有没有其他优雅的方法来做到这一点?

  5. 是否有可能早先拒绝大文件? 这个函数只在文件存储在/tmp之后被调用,攻击者可以通过简单的上传一个1000GB文件

这里有几个答案:

  1. fs.rename()将文件从A重命名为B,但不会复制该文件。 所以在成功重命名之后,pathA不再存在,所以你不能(不必)解除链接。
  2. 不知道为什么会这样。 /var/folders/XXX/YYY/T包含“每用户临时文件和caching” (请参阅$ man hier ),但Multiparty使用os.tmpDir() ,至less在我的Mac上返回/tmp (如预期)。
  3. 总之:你不能,除非你能find一个模块来提供这些types,我怀疑它是否存在。 你可能可以检查内容types对image/*video/*audio/* ,虽然;
  4. 我认为你仍然需要手动去做:

     var filePath = '/upload/' + file.name; var targetPath = dir.public + filePath; ... res.json({ path: filePath }); 
  5. 你传给connect-multiparty任何选项都会被传递给multiparty ,它有maxFilesSize选项。 这将限制所有file upload到一定的限制,但如果你只上传一个文件,它也应该工作;

我给你一个function可能是这可以帮助你上传文件虽然我已经完成它的图像上传,但很less修改这可能也适用于你..

  handleFileUpload: function(req) { if(!req.files || !req.files.place_img || !req.files.place_img.name) { return req.body.currentPicture || ''; } var data = fs.readFileSync(req.files.place_img.path); var fileName = req.files.place_img.name; var uid = crypto.randomBytes(10).toString('hex'); var dir = __dirname +"/../public/uploads/" + uid; fs.mkdirSync(dir, '0777'); fs.writeFileSync(dir + "/" + fileName, data); return '/uploads/' + uid + "/" + fileName; }