You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js使用Formidable上传docx文件存储路径配置问题

docx文件上传至Node.js服务器存储问题修复方案

实现目标

基于Chrome浏览器、Node.js + HTML + JavaScript技术栈,实现客户端向部署在EC2的Node.js Web服务器上传.docx格式文件,上传后文件存储到服务器指定目录。


现有实现代码

前端HTML片段

<body bgcolor=d9d9d9>
    <form action="https://kvyfcz.sse.codesandbox.io/upload" method="POST" id=form1 enctype="multipart/form-data">
        <h3>Please load the Doc File</h3>
        <b>Step 1
        <input type="file" id=docxFile accept=".doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document" name="filetoupload" />
        <input type="submit" />
        <!-- <button type="submit" form="form1" value="Submit">Upload</button> -->
    </form>

服务端Node.js代码

http
    .createServer(function (req, res) {
        if (req.url === "/upload") {
        res.write("<h1>Dirname is {" + __dirname + "}<br>");
        var form = new formidable.IncomingForm();
        form.parse(req, function (err, fields, file) {
        var oldpath = file.filetoupload.filepath;
        var newpath = __dirname + file.filetoupload.originalFilename;
        fs.rename(oldpath, newpath, function (error) {
            if (error) res.write("Rename Error occurred!!");
            var output1 = "oldpath is {" + oldpath + "} & newpath is {" + newpath + "} & Dirname is {" + __dirname + "}";
            res.write(output1);
            fs.readFile(newpath, "utf-8", function (err, data) {
            if (err) res.write("FS Error occurred!!");
            else {
                res.write(data);
            }
        });
    });
});

当前运行输出

Dirname is {/sandbox}
oldpath is {/tmp/83f13a67b2e8a684fd4ddbd01} & newpath is {/sandboxIronman - TestMe.docx} & Dirname is {/sandbox}PK!K���l[Content_Types].xml �(�̗

问题根因

当前Formidable可正常解析上传文件,重命名操作无报错,但存在核心问题:

  1. 文件未存入预期目录:Formidable默认将上传的临时文件存放在系统临时目录(Linux环境下为/tmp),由于路径拼接错误,fs.rename实际将文件移动到了系统根目录下名为sandboxIronman - TestMe.docx的位置,而非Node.js进程运行的/sandbox目录,因此在预期目录找不到文件。
  2. 路径拼接逻辑错误:直接字符串拼接__dirname和文件名时,缺少Linux系统路径分隔符/,导致生成的路径不符合预期;如果直接用原始文件名作为目标路径,Node.js会以进程启动时的工作目录(process.cwd())为基准寻址,和js文件所在目录(__dirname)不一定一致,极易触发路径不存在或权限报错。
  3. 额外现象说明:.docx本质是zip格式的二进制压缩包,用utf-8编码读取后直接返回给前端必然出现乱码,即输出中PK!开头的乱码内容,属于正常现象,不是文件损坏。

修复方案

  1. 使用Node.js内置path模块拼接路径:调用path.join()方法拼接路径,该方法会自动适配操作系统的路径分隔符,从根源避免漏写分隔符的问题。
  2. 指定明确的绝对存储路径:如果需要将文件存在js文件所在目录,用__dirname作为路径前缀;如果需要存在Node.js进程启动的工作目录,用process.cwd()作为前缀。建议单独创建upload目录作为固定存储位置,提前判断目录是否存在,不存在则自动创建。
  3. 移除用utf-8读取docx文件返回的逻辑,避免无意义的乱码输出。

修复后的服务端代码

const http = require('http');
const fs = require('fs');
const path = require('path');
const formidable = require('formidable');

// 配置文件存储目录,此处示例为js文件同目录下的upload文件夹,可自行替换为EC2上的目标绝对路径
const UPLOAD_DIR = path.join(__dirname, 'upload');
// 启动时检查存储目录,不存在则递归创建
if (!fs.existsSync(UPLOAD_DIR)) {
    fs.mkdirSync(UPLOAD_DIR, { recursive: true });
}

http.createServer(function (req, res) {
    // 仅处理POST方法的/upload请求
    if (req.url === "/upload" && req.method.toLowerCase() === 'post') {
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
        const form = new formidable.IncomingForm();
        form.parse(req, function (err, fields, files) {
            if (err) {
                res.write("文件解析失败");
                res.end();
                return;
            }
            const uploadFile = files.filetoupload;
            const tempPath = uploadFile.filepath;
            // 正确拼接目标存储路径
            const targetPath = path.join(UPLOAD_DIR, uploadFile.originalFilename);

            fs.rename(tempPath, targetPath, function (renameErr) {
                if (renameErr) {
                    res.write("文件存储失败:" + renameErr.message);
                    res.end();
                    return;
                }
                res.write("<h1>文件上传成功</h1>");
                res.write(`<p>临时文件路径:${tempPath}</p>`);
                res.write(`<p>文件最终存储路径:${targetPath}</p>`);
                res.end();
            });
        });
    }
}).listen(3000, () => {
    console.log('服务已启动,监听3000端口');
});

部署注意事项

  • 部署到EC2时,需要确保Node.js进程对配置的存储目录有写入权限,避免触发权限报错。
  • 提前配置EC2安全组,开放服务监听端口的入站规则,前端form的action属性需要替换为EC2的公网IP+对应端口。
  • 生产环境建议对上传文件做后缀、MIME类型校验,同时对文件重命名避免同名文件覆盖,防止恶意文件上传。

内容的提问来源于stack exchange,提问作者Aargee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 04:36:21