利用formidable上传文件,并利用Date对象重命名的方法讨论
本人新手,刚编程不久,刚学nodejs不久,请多指教。
直接入题了。日常中处理FROM的POST请求是很常见的。上传文件也是一个常见功能。编了一段代码,对上传的文件进行了储存和重命名,大家可以看看,不知道是不是一个不错的方案,还有没有错误或者值得优化的地方。另外,有没有上传相同的文件时(不管是不是同样的文件名),能不能不生成重复的文件呢?
function uploadfiles(res, req) {
console.log("Request handle 'uploadfiles' was called.");
var form = new formidable.IncomingForm();
console.log("about to parse");
form.parse(req, function(error, fields, files) {
console.log("parsing done");
var types = files.upload.name.split('.'); //将文件名以.分隔,取得数组最后一项作为文件后缀名。
console.log(types);
var date = new Date();
var ms = Date.parse(date); //计算当前时间与1970年1月1日午夜相差的毫秒数 赋值给ms以确保文件名无重复。
fs.renameSync(files.upload.path, "/tmp/files" + ms +"." + String(types[types.length-1]));
});
9 回复
简单的改写了一下 没有环境 未测试。没用用过那个什么form的东西,所以上传逻辑没有做修改。重命名修改了一下。
var crypto = require('crypto');
function isValidFileName(filename) {
var split = filename.split('.');
if (split.length < 2) {
return false;
}
return true;
}
function getExt(filename) {
var split = filename.split('.');
return split[split.length - 1];
}
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function randString(size) {
var result = '';
var allChar = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
size = size || 1;
while (size--) {
result += allChar.charAt(rand(0, allChar.length - 1));
}
return result;
}
function sha1(str) {
return crypto.createHash('sha1').update(str).digest('hex');
}
function randFilename() {
return sha1(randString(20) + new Date());
}
function uploadfiles(res, req) {
var form = new formidable.IncomingForm();
form.parse(req, function(error, fields, files) {
var ext = '';
if (isValidFileName(files.upload.name)) {
ext = getExt(files.upload.name);
} else {
// 错误处理
}
fs.renameSync(files.upload.path, "/tmp/files" + randFilename() +"." + ext);
});
}
如果不担心性能,可以对文件做md5或sha1,这样是最可以靠的。
function randFilename() {
return sha1(randString(rand(10, 100)) + new Date());
}
突然想起,这里可以进一步随机。
修改了一下函数名。还是没有测试。
var crypto = require('crypto');
function isValidFilename(filename) {
var split = filename.split('.');
if (split.length < 2) {
return false;
}
return true;
}
function getFilenameExt(filename) {
var split = filename.split('.');
return split[split.length - 1];
}
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function randString(size) {
var result = '';
var allChar = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
size = size || 1;
while (size--) {
result += allChar.charAt(rand(0, allChar.length - 1));
}
return result;
}
function sha1(str) {
return crypto.createHash('sha1').update(str).digest('hex');
}
function randFilename() {
return sha1(randString(rand(10, 100)) + new Date());
}
function uploadFile(res, req) {
var form = new formidable.IncomingForm();
form.parse(req, function(error, fields, files) {
var ext = '';
if (isValidFilename(files.upload.name)) {
ext = getFilenameExt(files.upload.name);
} else {
// 错误处理
}
fs.renameSync(files.upload.path, "/tmp/files" + randFilename() + "." + ext);
});
}
@darklowly 回复的有些晚,抱歉。非常感谢您的赐教。我测试了一下,的确是行的通的,可靠的做法。现在我在考虑如何让同样内容(可以不同名字)的文件经过算法能得到同样的代码,即减少重复文件的出现。不知道您有什么建议没?再次感谢您。
@ghostFrog 上面的回复 已经给你说过了 要对文件md5或sha1
(res,req) 好像位置反了吧?
磁盘保存的时候,文件名加上传时间到毫秒,一般就没有重复可能.
在对上传文件命名上,我也是采用时间戳,精确到毫秒还是不行的,重复的几率存在。NodeJS提供了纳秒的API,可以精确到纳秒,这样文件名是一串数字,便于排序也排除了重名的可能。