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;
            }
        })
    })

13 回复

在Node.js中处理文件上传时遇到Error: EPERM, rename '...'错误通常是因为文件操作权限问题或文件被其他进程占用。这个问题可能发生在尝试将临时文件移动到新位置时。以下是一些可能的原因及解决方案:

原因分析

  1. 权限不足:目标目录或文件没有写入权限。
  2. 文件被占用:在尝试重命名文件时,文件可能正被其他进程使用。
  3. 路径错误:路径可能包含非法字符或格式不正确。

解决方案

  1. 检查文件权限:确保Node.js进程有权限访问和修改目标目录。
  2. 确保文件未被占用:确保在移动文件之前文件未被其他进程使用。
  3. 正确的文件路径:确保文件路径正确无误。

示例代码改进

下面是改进后的代码示例,包括一些错误处理和日志记录以帮助调试问题:

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() 方法时,如果目标目录没有足够的写入权限,或者文件正在被其他进程使用,就会出现这个错误。

解决方案:

  1. 确保目标目录具有写入权限:检查 ./public/uploadimg/ 目录及其父目录是否具有写入权限。可以尝试修改目录权限或运行 Node.js 应用程序的用户权限。

  2. 正确使用 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 错误,并确保文件能够正确地从临时位置移动到目标位置。

回到顶部