Nodejs 利用formidable上传文件,并利用Date对象重命名的方法讨论
Nodejs 利用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]));
});
Node.js 利用 formidable 上传文件,并利用 Date 对象重命名的方法讨论
引言
作为一个初学者,我在学习 Node.js 的过程中遇到了一些问题。其中一个问题是如何处理表单上传文件的功能。我编写了一些代码来处理这个问题,并希望得到一些反馈和建议。
代码实现
下面是我目前的实现方法:
const formidable = require('formidable');
const fs = require('fs');
function uploadFiles(req, res) {
console.log("Request handle 'uploadFiles' was called.");
const form = new formidable.IncomingForm();
console.log("about to parse");
form.parse(req, (error, fields, files) => {
console.log("parsing done");
if (error) {
console.error("Error parsing the form:", error);
return res.status(500).send("Error uploading file.");
}
const { upload } = files;
if (!upload) {
return res.status(400).send("No file uploaded.");
}
const { path, name } = upload;
const [fileName, ext] = name.split('.');
// 获取当前时间戳
const date = new Date();
const timestamp = date.getTime();
// 重命名文件并移动到目标目录
const newPath = `/tmp/files/${timestamp}.${ext}`;
fs.rename(path, newPath, (err) => {
if (err) {
console.error("Error renaming file:", err);
return res.status(500).send("Error uploading file.");
}
console.log(`File renamed and moved to ${newPath}`);
res.send("File uploaded successfully.");
});
});
}
代码说明
- 引入模块:我们首先引入
formidable
和fs
模块。 - 创建表单解析器:使用
formidable.IncomingForm()
创建一个表单解析器实例。 - 解析表单数据:通过
form.parse(req, callback)
方法解析上传的数据。 - 获取文件信息:从解析后的
files
对象中获取上传的文件信息。 - 重命名文件:
- 使用
Date.now()
或new Date().getTime()
获取当前时间戳,确保文件名唯一。 - 将文件重命名为带有时间戳的新文件名。
- 使用
- 移动文件:使用
fs.renameSync()
或异步的fs.rename()
方法将文件移动到指定目录。 - 返回响应:根据操作结果返回相应的 HTTP 响应。
文件名重复问题
为了防止文件名重复,我们可以使用时间戳来生成唯一的文件名。这种方法简单有效,但可能不够理想,特别是在高并发情况下。更优的方法是使用 UUID 或其他唯一标识符。
结论
以上代码提供了一个基本的文件上传功能,并利用时间戳重命名文件以避免重复。希望这对你有所帮助!如果你有任何建议或改进意见,请告诉我。
简单的改写了一下 没有环境 未测试。没用用过那个什么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);
});
}
(res,req) 好像位置反了吧?
磁盘保存的时候,文件名加上传时间到毫秒,一般就没有重复可能.
在对上传文件命名上,我也是采用时间戳,精确到毫秒还是不行的,重复的几率存在。NodeJS提供了纳秒的API,可以精确到纳秒,这样文件名是一串数字,便于排序也排除了重名的可能。