如何让 multer 正确解析与表单数据一起发送的客户端请求?
How can I make multer parse a client request sent with form-data properly?
我想将数据从客户端传输到服务器计算机,两者都在使用 Node.js
。在客户端,我正在使用库 axios
和 form-data
。在我使用的服务器上 express
和 multer
...
我使用的客户端代码如下:
const FormData = require('form-data');
const axios = require('axios');
let form = new FormData();
form.append("user", "someuser");
axios({
method: 'post',
url: 'http://localhost:9996/data',
data: form
})
.then(function (response) {
console.log(response.status);
})
.catch(function (response) {
console.log(response.status);
});
服务器代码如下:
const express = require('express')
const bodyParser = require('body-parser');
const multer = require('multer')
const app = express();
const upload = multer();
app.use(bodyParser.urlencoded({extended: true}));
app.post('/data', upload.none(), function (req, res, next) {
console.log(req.body);
res.sendStatus(200)
})
const port = 9996;
app.listen(port, () => {
console.log(`running on port ${port}`)
})
.on('error', function(err) {
console.log('stopped')
})
此代码有效,我设法将我在客户端上创建的 form
JSON
作为服务器上的请求消息获取。但是,我的 req.body
在服务器上的输出如下:
{ '----------------------------926328179431047129531240\r\nContent-Disposition: form-data; name':
'"user"\r\n\r\nsomeuser\r\n----------------------------926328179431047129531240--\r\n' }
此输出未按我的预期格式化为 JSON 对象。 multer
中的参数 upload.none()
不是应该将 req.body
解析为 JSON 吗? 有谁知道我在这里弄错了什么以及是否需要更改任何其他参数才能使 req.body 上的输出格式化为 JSON 对象?
观察: 我知道如果我用 const form = {"user":"someuser"}
手动创建这个 JSON 我将在 req.body
上将输出作为对象在服务器上。但是,我正在使用 form-data
因为在我的原始代码中我计划在客户端读取一个带有 createReadStream
的大文件并在服务器上用 createWriteStream
写入它,而库 form-data
是我发现 axios
支持数据流的解决方案。
const storage = multer.memoryStorage() ;
let upload = multer({
storage,
fileFilter: (req, file, cb) => {
//if (mimeTypes.includes(file.mimetype)) {
return cb(null, true);
//}
//cb('File type not allowed', false);
}
}).any();
router
.post('/',(req,res)=>{
upload(req, res, (err) => {
if (err) {
// An error occurred when uploading to server memory
return res.status(502).json(err) ;
}
console.log(req.body);
console.log(req.files);
....
您看到的原因是 multer
仅在 content-type
header 设置为 multipart/form-data
[=22= 时解析请求].您没有设置请求 headers,因此使用 application/x-www-form-urlencoded
发送请求,multer
忽略它并改为 body-parser
进行解析。
要修复它,请按您的要求设置 headers,如下所示:
const FormData = require("form-data");
const axios = require("axios");
let form = new FormData();
form.append("user", "someuser");
// form.append("my_buffer", Buffer.alloc(10)); // or actual image
axios({
method: "post",
url: "http://localhost:8080/data",
data: form,
headers: form.getHeaders()
})
.then(function(response) {
console.log(response.status);
})
.catch(function(response) {
console.log(response.status);
});
之前的一个答案 (@Michal Levy) 已经提到 multer
需要在您的客户端 HTML 表单中声明 enctype="multipart/form-data" 。
这是直接来自文档的示例:
<form action="/profile" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" />
</form>
接下来,您关于 multer.null()
的问题(可能是一个陈述)应该 return req.body 中的一个 JSON 对象 - 我认为这是 不正确。
如果表单仅包含文本字段,则应使用 Based again on the docs、multer.null()
:
In case you need to handle a text-only multipart form, you should use the .none() method.
因此,这表明您可能无法在开箱即用的 req.body 中获得 JSON。
此外,您在代码段中登录的输出很可能来自请求对象,而不是 multer
本身。我会在一秒钟内解决这个问题。
这是一个片段,将向您展示如何正确使用 multer
服务器端以及如何在非常高的级别上记录您的结果,而不考虑内存存储等。
返回您的客户端代码,确保您有一个 HTML 表单,其中包含正确的 enctype
,否则 multer
将无法工作。
删除您的 multer.null()
方法,因为它对您没有任何帮助,但允许您仅加载纯文本表单,而不是 JSON 预格式化输出。
改为包括这样的内容:
const multer = require("multer");
const upload = multer().single("name_field_in_your_form"); // this is the fieldname in your form if you want to upload a single file only
在处理表单的模块中,让 multer
处理错误而不是将其留给 express
...这样您可以在加载时捕获错误:
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
console.log("MultiError occured when uploading");
return;
}
else if (err) {
console.log(err);
return;
}
将字段字符串化并从multer
中间件中获取您想要的数据:
const { fieldname1example, fieldname2example } = JSON.stringify(req.body);
const yourMulterFile = req.file;
记录 yourMulterFile 变量并转换为 JSON 您感兴趣的数据。
如果您对文件本身感兴趣以进行进一步处理,请查看 .buffer
属性,其中 return 顾名思义是上传文件的缓冲区。
如果这不能解决或澄清问题,请告诉我。
我想将数据从客户端传输到服务器计算机,两者都在使用 Node.js
。在客户端,我正在使用库 axios
和 form-data
。在我使用的服务器上 express
和 multer
...
我使用的客户端代码如下:
const FormData = require('form-data');
const axios = require('axios');
let form = new FormData();
form.append("user", "someuser");
axios({
method: 'post',
url: 'http://localhost:9996/data',
data: form
})
.then(function (response) {
console.log(response.status);
})
.catch(function (response) {
console.log(response.status);
});
服务器代码如下:
const express = require('express')
const bodyParser = require('body-parser');
const multer = require('multer')
const app = express();
const upload = multer();
app.use(bodyParser.urlencoded({extended: true}));
app.post('/data', upload.none(), function (req, res, next) {
console.log(req.body);
res.sendStatus(200)
})
const port = 9996;
app.listen(port, () => {
console.log(`running on port ${port}`)
})
.on('error', function(err) {
console.log('stopped')
})
此代码有效,我设法将我在客户端上创建的 form
JSON
作为服务器上的请求消息获取。但是,我的 req.body
在服务器上的输出如下:
{ '----------------------------926328179431047129531240\r\nContent-Disposition: form-data; name':
'"user"\r\n\r\nsomeuser\r\n----------------------------926328179431047129531240--\r\n' }
此输出未按我的预期格式化为 JSON 对象。 multer
中的参数 upload.none()
不是应该将 req.body
解析为 JSON 吗? 有谁知道我在这里弄错了什么以及是否需要更改任何其他参数才能使 req.body 上的输出格式化为 JSON 对象?
观察: 我知道如果我用 const form = {"user":"someuser"}
手动创建这个 JSON 我将在 req.body
上将输出作为对象在服务器上。但是,我正在使用 form-data
因为在我的原始代码中我计划在客户端读取一个带有 createReadStream
的大文件并在服务器上用 createWriteStream
写入它,而库 form-data
是我发现 axios
支持数据流的解决方案。
const storage = multer.memoryStorage() ;
let upload = multer({
storage,
fileFilter: (req, file, cb) => {
//if (mimeTypes.includes(file.mimetype)) {
return cb(null, true);
//}
//cb('File type not allowed', false);
}
}).any();
router
.post('/',(req,res)=>{
upload(req, res, (err) => {
if (err) {
// An error occurred when uploading to server memory
return res.status(502).json(err) ;
}
console.log(req.body);
console.log(req.files);
....
您看到的原因是 multer
仅在 content-type
header 设置为 multipart/form-data
[=22= 时解析请求].您没有设置请求 headers,因此使用 application/x-www-form-urlencoded
发送请求,multer
忽略它并改为 body-parser
进行解析。
要修复它,请按您的要求设置 headers,如下所示:
const FormData = require("form-data");
const axios = require("axios");
let form = new FormData();
form.append("user", "someuser");
// form.append("my_buffer", Buffer.alloc(10)); // or actual image
axios({
method: "post",
url: "http://localhost:8080/data",
data: form,
headers: form.getHeaders()
})
.then(function(response) {
console.log(response.status);
})
.catch(function(response) {
console.log(response.status);
});
之前的一个答案 (@Michal Levy) 已经提到 multer
需要在您的客户端 HTML 表单中声明 enctype="multipart/form-data" 。
这是直接来自文档的示例:
<form action="/profile" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" />
</form>
接下来,您关于 multer.null()
的问题(可能是一个陈述)应该 return req.body 中的一个 JSON 对象 - 我认为这是 不正确。
Based again on the docs、multer.null()
:
In case you need to handle a text-only multipart form, you should use the .none() method.
因此,这表明您可能无法在开箱即用的 req.body 中获得 JSON。
此外,您在代码段中登录的输出很可能来自请求对象,而不是 multer
本身。我会在一秒钟内解决这个问题。
这是一个片段,将向您展示如何正确使用 multer
服务器端以及如何在非常高的级别上记录您的结果,而不考虑内存存储等。
返回您的客户端代码,确保您有一个 HTML 表单,其中包含正确的
enctype
,否则multer
将无法工作。删除您的
multer.null()
方法,因为它对您没有任何帮助,但允许您仅加载纯文本表单,而不是 JSON 预格式化输出。改为包括这样的内容:
const multer = require("multer"); const upload = multer().single("name_field_in_your_form"); // this is the fieldname in your form if you want to upload a single file only
在处理表单的模块中,让
multer
处理错误而不是将其留给express
...这样您可以在加载时捕获错误:upload(req, res, function (err) { if (err instanceof multer.MulterError) { console.log("MultiError occured when uploading"); return; } else if (err) { console.log(err); return; }
将字段字符串化并从
multer
中间件中获取您想要的数据:const { fieldname1example, fieldname2example } = JSON.stringify(req.body); const yourMulterFile = req.file;
记录 yourMulterFile 变量并转换为 JSON 您感兴趣的数据。 如果您对文件本身感兴趣以进行进一步处理,请查看
.buffer
属性,其中 return 顾名思义是上传文件的缓冲区。
如果这不能解决或澄清问题,请告诉我。