Nodejs 上传图片报错Error: EPERM, rename ''...........''
Nodejs 上传图片报错Error: EPERM, rename ‘’…’’
//图片上传路由 app.post(’/uploadImg’,function(req, res, next){ console.log(req.files); console.log(“name=”+req.body.localUrl); console.log(“文件的临时路径:”+req.files.imgFile.path);//这是文件的临时路径 console.log(‘get?dir=’+req.query.dir);
var tpm_path = req.files.imgFile.path;
var form = new formidable.IncomingForm();
form.keepExtensions = true;//保留后缀 .jpg/.png
var folderName = new Date().Format('yyyy-MM-dd');
var dirPath = "./public/uploadimg/"+folderName;//指定路径
console.log(dirPath);
if(!fs.existsSync(dirPath)){//如果没有这个文件夹就创建文件夹
fs.mkdirSync(dirPath);
}
//移动文件到指定路径
fs.rename(tpm_path, dirPath, function(err){
if(err){
throw err;
}
//删除临时文件
fs.unlink(tpm_path, function(err){
if(err){
throw err;
}
})
})
在Node.js中处理文件上传时遇到Error: EPERM, rename '...'
错误通常是因为文件操作权限问题或文件被其他进程占用。这个问题可能发生在尝试将临时文件移动到新位置时。以下是一些可能的原因及解决方案:
原因分析
- 权限不足:目标目录或文件没有写入权限。
- 文件被占用:在尝试重命名文件时,文件可能正被其他进程使用。
- 路径错误:路径可能包含非法字符或格式不正确。
解决方案
- 检查文件权限:确保Node.js进程有权限访问和修改目标目录。
- 确保文件未被占用:确保在移动文件之前文件未被其他进程使用。
- 正确的文件路径:确保文件路径正确无误。
示例代码改进
下面是改进后的代码示例,包括一些错误处理和日志记录以帮助调试问题:
const express = require('express');
const formidable = require('formidable');
const fs = require('fs');
const app = express();
app.post('/uploadImg', (req, res) => {
const form = new formidable.IncomingForm();
form.parse(req, (err, fields, files) => {
if (err) {
return res.status(500).send({ error: "Form parse error" });
}
const tempPath = files.imgFile.path;
const targetDir = `./public/uploadimg/${new Date().toISOString().slice(0, 10)}`; // 使用ISO日期字符串作为文件夹名
console.log(`Temp path: ${tempPath}`);
console.log(`Target directory: ${targetDir}`);
try {
// 确保目标目录存在
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true });
}
// 移动文件
fs.rename(tempPath, `${targetDir}/${files.imgFile.name}`, (err) => {
if (err) {
console.error("Error moving file:", err);
return res.status(500).send({ error: "Failed to move file" });
}
// 删除临时文件
fs.unlink(tempPath, (err) => {
if (err) {
console.error("Error deleting temporary file:", err);
return res.status(500).send({ error: "Failed to delete temporary file" });
}
res.send({ message: "File uploaded successfully" });
});
});
} catch (e) {
console.error("Error:", e);
res.status(500).send({ error: "Internal server error" });
}
});
});
app.listen(3000, () => {
console.log("Server running on port 3000");
});
关键点解释
- 文件夹名生成:使用ISO日期字符串作为文件夹名,避免时间戳导致的冲突。
- 错误处理:增加了更多的错误处理逻辑,确保在发生错误时能够返回有意义的信息。
- 递归创建目录:使用
fs.mkdirSync
的{ recursive: true }
选项,确保即使父目录不存在也能成功创建。
通过这些改进,可以更好地处理文件上传过程中可能出现的问题。
{ imgFile: { fieldName: ‘imgFile’, originalFilename: ‘pic.jpg’, path: ‘public\uploadimg\1128-gapt0h.jpg’, headers: { ‘content-disposition’: ‘form-data; name=“imgFile”; filename=“pic.jpg”’, ‘content-type’: ‘image/jpeg’ }, ws: { _writableState: [Object], writable: true, domain: null, _events: [Object], _maxListeners: 10, path: ‘public\uploadimg\1128-gapt0h.jpg’, fd: null, flags: ‘w’, mode: 438, start: undefined, pos: undefined, bytesWritten: 57771, closed: true, open: [Function], _write: [Function], destroy: [Function], close: [Function], destroySoon: [Function], pipe: [Function], write: [Function], end: [Function], setMaxListeners: [Function], emit: [Function], addListener: [Function], on: [Function], once: [Function], removeListener: [Function], removeAllListeners: [Function], listeners: [Function] }, size: 57771, name: ‘pic.jpg’, type: ‘image/jpeg’ } } name=C:\fakepath\pic.jpg 文件的临时路径:public\uploadimg\1128-gapt0h.jpg get?dir=image ./public/2014-05-26/
G:\NodeJsWorkspace\blog\routes\index.js:240 throw err; ^ Error: EPERM, rename ‘G:\NodeJsWorkspace\blog\public\uploadimg\1128-gapt0h.jpg’
和操作系统有关么?win7的
目录存在啊?怎么回事?
为什么不直接保存还要放在临时文件里面??
Error: EPERM 会不会是权限问题?
上传时都会报错到临时文件夹里的,如果不设置临时文件夹,会报错到C:User…目录下的
我查看了,文件夹都是可读写的设置
http://cnodejs.org/topic/4f40a4dc0feaaa4424081758 你的代码是不是有问题?看下这个文章
嗯,我看过这篇文章,按照这篇文章修改过也不行,我好像看到了他的评论也有这个问题
rename本身就是移动+删除,不需要unlink
删除unlink也不行,问题出现在rename上
你遇到的 Error: EPERM
错误通常是由于权限问题导致的。在 Node.js 中使用 fs.rename()
方法时,如果目标目录没有足够的写入权限,或者文件正在被其他进程使用,就会出现这个错误。
解决方案:
-
确保目标目录具有写入权限:检查
./public/uploadimg/
目录及其父目录是否具有写入权限。可以尝试修改目录权限或运行 Node.js 应用程序的用户权限。 -
正确使用
fs.rename()
方法:fs.rename()
方法需要两个参数,源文件路径和目标文件的完整路径(包括文件名)。你当前的代码中,dirPath
只是目标目录的路径,而缺少文件名。
示例代码:
const fs = require('fs');
const path = require('path');
const formidable = require('formidable');
app.post('/uploadImg', function(req, res, next) {
console.log(req.files);
console.log("name=" + req.body.localUrl);
console.log("文件的临时路径:" + req.files.imgFile.path);
const tempPath = req.files.imgFile.path;
const form = new formidable.IncomingForm();
form.keepExtensions = true;
const folderName = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '').slice(0, 19);
const dirPath = path.join(__dirname, 'public', 'uploadimg', folderName);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
// 构建目标文件的完整路径
const targetFilePath = path.join(dirPath, path.basename(req.files.imgFile.name));
// 移动文件到指定路径
fs.rename(tempPath, targetFilePath, function(err) {
if (err) {
return res.status(500).send({ error: "文件移动失败:" + err.message });
}
// 删除临时文件
fs.unlink(tempPath, function(err) {
if (err) {
return res.status(500).send({ error: "临时文件删除失败:" + err.message });
}
return res.send({ message: "文件上传成功" });
});
});
});
关键点解释:
- 目标文件路径:使用
path.join()
构建完整的文件路径。 - 权限检查:确保目标目录存在,并且应用程序有足够的权限写入该目录。
- 递归创建目录:使用
{ recursive: true }
选项来确保中间目录也被创建。 - 错误处理:返回适当的错误信息而不是抛出异常,以便客户端能够了解发生了什么问题。
这样可以避免 EPERM
错误,并确保文件能够正确地从临时位置移动到目标位置。