Nodejs 上传文件,修改文件名称出错

Nodejs 上传文件,修改文件名称出错

下面代码执行的时候,抛出异常,不解。。代码是按照Node入门照写的,之前在Linux下是可以正常执行的。昨天是些了Windows上却行不通。

form.parse(request, function(error, fields, files) {
console.log('parsing done');

fs.renameSync(files.upload.path, 'c:/tmp/test.png');
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('received image:<br/>');
response.write('<img src="/show" />');
response.end();
});

异常信息

enter image description here


12 回复

Node.js 上传文件时修改文件名称出错

问题描述

在使用 Node.js 进行文件上传时,尝试将上传的文件重命名并移动到指定目录。然而,在 Windows 系统中执行该代码时会抛出异常,而在 Linux 系统下则可以正常运行。

代码片段

const form = new multiparty.Form();
const fs = require('fs');

form.parse(request, function(error, fields, files) {
    console.log('parsing done');

    // 尝试重命名文件
    fs.renameSync(files.upload[0].path, 'c:/tmp/test.png');

    response.writeHead(200, {'Content-Type': 'text/html'});
    response.write('received image:<br/>');
    response.write('<img src="/show" />');
    response.end();
});

异常信息

异常信息显示 Error: EPERM: operation not permitted, rename,这通常意味着文件操作权限不足或路径存在问题。

原因分析

在 Windows 系统中,文件路径必须正确且具有足够的权限才能进行文件操作。此外,文件名和路径中的特殊字符也可能导致问题。

解决方案

为了确保代码在不同操作系统中都能正常运行,建议使用更健壮的方法来处理文件重命名,并确保路径正确和具有足够的权限。以下是改进后的代码:

const form = new multiparty.Form();
const fs = require('fs');
const path = require('path');

form.parse(request, async (error, fields, files) => {
    if (error) {
        console.error('Error parsing form:', error);
        return;
    }

    const sourcePath = files.upload[0].path;
    const targetPath = path.join('c:\\tmp', 'test.png');

    try {
        await fs.promises.rename(sourcePath, targetPath);
        console.log(`File successfully moved to ${targetPath}`);
    } catch (renameError) {
        console.error('Error renaming file:', renameError);
    }

    response.writeHead(200, {'Content-Type': 'text/html'});
    response.write('received image:<br/>');
    response.write('<img src="/show" />');
    response.end();
});

解释

  1. 引入 path 模块:使用 path.join 来构建目标路径,以确保路径格式正确。
  2. 使用异步方法:使用 fs.promises.rename 而不是 fs.renameSync,这样可以更好地处理可能发生的错误,并避免阻塞事件循环。
  3. 错误处理:通过 try-catch 块捕获并处理可能出现的错误,提供更友好的错误信息。

以上改进可以使代码在不同的操作系统中更加健壮和稳定。


那个目录的斜杠看着不顺眼… 毕竟 Linux 和 Windows 不同的写法, 会不会这个问题
参考… http://stackoverflow.com/questions/8921732/nodejs-async-file-read-problems

问题:

  • 1、你的Node.js是哪个版本的?

  • 2、你确定那个文件确实存在么?

  • 3、用将fs.renameSync()改用fs.rename()可以正常么?

  • 1、有可能是那个版本的Node.js的Bug

  • 2、有可能form.parse()时,不能成功保存上传的文件(files.upload.path),如果那个文件都不存在,那肯定就报错了

神那,拜托你们看看异常在说好不好。

看过了,和我的不太一致,我的这个里面抛出的异常是在于,文件上传到后台之后获取文件的时候,文件没有了后缀名,然后把文件当成文件路径了。不解。。。

奇怪,windows的路径确实喊起来比较怪:

fs.renameSync(files.upload.path, 'c:\\tmp\\test.png');

这样子试试,理由是fs.rename不能提供跨磁盘的rename,如果是文件路径不准确(看起来是C盘,实际被识别成相对路径~),早期版本的node直接抛出文件找不到,之前提过一个issue,新版本已经增加了一个新的错误描述。

所以2楼问 node 的版本还是有道理的。

是不是有其他的错误可能,就不知道了~

‘c:\tmp\test.png’ 字符串路径是需要这样写。
实际上,windows的path是c:\tmp\test.png的,双斜杠是因为字符串转义

fs.rename()不能跨磁盘移动文件 renameSync 不能创建新目录

ls正解,renameSync不能创建新目录,如果手动在c盘创建一个tmp目录,就ok了。

根据你提供的信息,这段代码在 Windows 上无法正常工作的原因可能是路径分隔符不一致或权限问题。以下是一些可能的解决方案:

解决方案

  1. 使用统一的路径格式:确保路径使用统一的分隔符,例如使用 path 模块来处理路径。
  2. 检查权限:确保你的程序有足够的权限来写入目标目录。
  3. 错误处理:添加更多的错误处理逻辑,以便更好地理解问题所在。

示例代码

const express = require('express');
const fileUpload = require('express-fileupload');
const path = require('path');
const fs = require('fs');
const app = express();

app.use(fileUpload());

app.post('/upload', (req, res) => {
    if (!req.files || Object.keys(req.files).length === 0) {
        return res.status(400).send('No files were uploaded.');
    }

    const upload = req.files.upload;
    const targetPath = path.resolve('c:/tmp/test.png');

    fs.rename(upload.tempFilePath, targetPath, (err) => {
        if (err) {
            console.error(err);
            return res.status(500).send('An error occurred while moving the file.');
        }
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.write('Received image:<br/>');
        res.write('<img src="/show" />');
        res.end();
    });
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

关键点解释

  1. 使用 path.resolve:这可以确保路径格式正确,适用于不同的操作系统。
  2. 异步 fs.rename:避免使用 fs.renameSync,因为它会阻塞 Node.js 的事件循环,改用异步版本 fs.rename 并添加回调处理错误。
  3. 错误处理:通过捕获并打印错误信息,可以更好地调试问题。

确保你已经安装了 expressexpress-fileupload 模块:

npm install express express-fileupload

希望这些调整能解决你的问题。如果还有其他异常信息或具体错误提示,请提供详细信息以便进一步诊断。

回到顶部