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)
有几个问题。
-
无法mkdir。 错误在断开连接
ENOENT,unlink'/var/folders/5p/qqz2vyhd3yqb_334h6fj7_y00000gq/T/O3BTOo3rXdKRT3Zfs5JPUpn8.png'
-
为什么上面的
/var/folders
下的tmpPath? 从我读的所有教程中,它应该存储在[app_root]/tmp
-
除了检查文件大小,我怎么只允许图像,audio和video? 我需要支持所有可以embedded和标记的types,并拒绝其他所有的types。 我知道有一个
file.type
值,但我不想硬编码。 我如何检查文件types是否可以在HTML5标签中使用? -
在我的成功callback中,我发回
{path: targetPath}
供客户端标记使用。 但是targetPath是/path/to/app_root/public/upload/xxx.png
,我怎么才能发回/public/upload/xxx.png
? 我当然可以searchpublic
和剥离/path/to/app_root/
但代码会变得混乱。 有没有其他优雅的方法来做到这一点? -
是否有可能早先拒绝大文件? 这个函数只在文件存储在
/tmp
之后被调用,攻击者可以通过简单的上传一个1000GB文件
这里有几个答案:
-
fs.rename()
将文件从A重命名为B,但不会复制该文件。 所以在成功重命名之后,pathA不再存在,所以你不能(不必)解除链接。 - 不知道为什么会这样。
/var/folders/XXX/YYY/T
包含“每用户临时文件和caching” (请参阅$ man hier
),但Multiparty使用os.tmpDir()
,至less在我的Mac上返回/tmp
(如预期)。 - 总之:你不能,除非你能find一个模块来提供这些types,我怀疑它是否存在。 你可能可以检查内容types对
image/*
,video/*
和audio/*
,虽然; -
我认为你仍然需要手动去做:
var filePath = '/upload/' + file.name; var targetPath = dir.public + filePath; ... res.json({ path: filePath });
- 你传给
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; }