使用express-fileupload中间件上传文件报错“errno“:-4058,“code“:“ENOENT“,“syscall“:“open“

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用express-fileupload中间件上传文件报错“errno“:-4058,“code“:“ENOENT“,“syscall“:“open“相关的知识,希望对你有一定的参考价值。

异常

当上传文件后浏览器显示:

"errno":-4058,"code":"ENOENT","syscall":"open","path":"D:\\\\NodeJs\\\\node-demo\\\\upload\\\\img\\\\IMG1604419333167.jpg"

而控制台也打印错误栈:

node:_http_outgoing:576
    throw new ERR_HTTP_HEADERS_SENT('set');
    ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:371:5)
    at ServerResponse.setHeader (node:_http_outgoing:576:11)
    at ServerResponse.header (D:\\NodeJs\\node-demo\\node_modules\\express\\lib\\response.js:771:10)
    at ServerResponse.send (D:\\NodeJs\\node-demo\\node_modules\\express\\lib\\response.js:170:12)
    at D:\\NodeJs\\node-demo\\upload.js:27:18
    at D:\\NodeJs\\node-demo\\node_modules\\express-fileupload\\lib\\utilities.js:56:57
    at WriteStream.<anonymous> (D:\\NodeJs\\node-demo\\node_modules\\express-fileupload\\lib\\utilities.js:181:29)
    at WriteStream.emit (node:events:390:28)
    at emitCloseNT (node:internal/streams/destroy:145:10)
    at emitErrorCloseNT (node:internal/streams/destroy:130:3) 
  code: 'ERR_HTTP_HEADERS_SENT'


Node.js v17.1.0

错误代码

// 第一步,引入express
var express = require("express");
// 引入文件上传模块express-fileupload
var fileUpload = require('express-fileupload');

// 第二步,创建服务器应用程序
var app = express();
// 配置文件上传模块
app.use(fileUpload());

app.post('/upload', function (request, response) 
    var avatarFile = request.files.avatar;
    console.log(avatarFile);
    // 处理文件上传失败
    if (!request.files || Object.keys(request.files).length === 0) 
        return response.static(400).send("没有文件被上传!")
    
    // 获取上传文件名
    var fileName = avatarFile.name;// 注意avatar对应input标签的name属性值
    // 设定文件的保存路径
    var uploadPath = __dirname + "/upload/img/" + fileName;
    // 使用mv方法来将上传文件保存到指定路径下
    // mv(filePath, callback)有两个参数:filePath指定是上传文件的保存路径,callback是回调函数用来处理错误并且有一个参数err表示错误对象
    avatarFile.mv(uploadPath, function (err) 
        if (err)
            return response.status(500).send(err);
        response.send('文件上传成功!');
    );
);

// 监听端口
app.listen(8989, function () 
    console.log("app is running at port 8989.");
);

原因

实际上代码没有任何问题。具体原因可参考官网issue

究其原因在于ar uploadPath = __dirname + "/upload/img/" + fileName;这一行。

__dirname表示当前js文件所在目录,肯定是存在的,但是/upload/img这是一个目录,是我们要保存上传文件到的指定目录,但该目录不存在(即没有被创建),这就是导致上面问题的关键,我们必须手动创建这个目录,代码不会给你自动创建不存在的目录fileName表示上传文件的文件名。

解决

手动创建/upload/img目录。

以上是关于使用express-fileupload中间件上传文件报错“errno“:-4058,“code“:“ENOENT“,“syscall“:“open“的主要内容,如果未能解决你的问题,请参考以下文章

如何从不同的上传点在同一页面上上传多个文件。使用 nodejs express-fileupload

从express js访问HTML元素

使用具有角度7平均堆栈的multer中间件上传文件不起作用

node实现图片上传功能

express文件上传中间件Multer详解

总结 | 文件上传绕过方式和中间件解析漏洞