Getting ERROR: uncaughtException: source.on is not a function, when using request and multiparty for multipart/form-data
Getting ERROR: uncaughtException: source.on is not a function, when using request and multiparty for multipart/form-data
我正在尝试将数据从我的节点应用程序发送到第 3 方 HTTP 端点。
我正在使用多方模块解析来自客户端的请求 object 上的数据,并通过请求模块发送数据。我收到错误
错误:未捕获异常:source.on 不是函数
var request = require('request');
const multiparty = require('multiparty');
function addAttachment(req, res) {
let form = new multiparty.Form();
let parsedFile = {};
const formData = {};
form.parse(req, function(err, fields, files){
Object.keys(fields).forEach(function(name) {
formData[name] = fields[name][0];
});
Object.keys(files).forEach(function(name) {
logger.debug(name);
parsedFile[name] = files[name][0];
});
formData.uploadFile = parsedFile.uploadFile;
logger.debug('formData ', formData);
reqOptions.url = imageURL;
reqOptions.formData = formData;
logger.debug('REQ_OPTIONS ', reqOptions);
request.post(reqOptions, function (err, response, body) {
if (err) {
logger.warn(req, ' Error sending attachment', err);
res.status(400);
res.json({ "msg": "Error sending attachment" });
} else {
res.status(201);
logger.debug('BODY ', body);
res.send(body);
}
});
});
}
reqOptions
obj包含headers、url、auth obj,我们再往里面添加表单数据。
当我记录表单数据时,它看起来格式正确
{
"meta": {
"prop1": "xxxxxx",
"prop2": "xxxxxxxxxxxxx",
"uploadFile": {
"fieldName": "uploadFile",
"originalFilename": "test.PNG",
"path": "/tmp/W1IppPiK04JpkPrnZWEhzkmV.PNG",
"headers": {
"content-disposition": "form-data; name=\"uploadFile\"; filename=\"test.PNG\"",
"content-type": "image/png"
},
"size": 42786
}
}
}
所以经过一些摸索和挖掘,我能够 post 向外部 API 形成数据。我决定将我使用的节点模块更改为 connect-multiparty
。 Connect 将解析请求 headers 并解码 post-form-data 允许您访问来自 req
obj 的数据 E.G req.body
现在具有添加的属性并且 req.files
具有上传的文件。
const multipart = require('connect-multiparty');
const multipartMiddleware = multipart();
然后将multipartMiddleware
添加到路由中。
app.post('/api/addAttachment' multipartMiddleware, MyController.addAttachment);
然后在我的控制器文件中,我将代码更改为使用 connect-multipart
。
const fs = require('fs');
var request = require('request');
function addAttachment(req, res) {
const TMP = '/tmp';
let formData = {};
Object.keys(req.body).forEach((propName) =>{
if (typeof propName === 'string') {
logger.debug(propName, ' is a string');
formData[propName] = req.body[propName];
} else {
logger.debug(propName, ' is not a string')
}
});
//The files get added to the tmp folder on the files system,
//So we create a stream to read from tmp folder,
//at the end end we need to delete the file
formData['uploadFile'] = fs.createReadStream(req.files.uploadFile.path);
logger.debug('FORM DATA ', formData, '\n');
reqOptions.url = imageUrl;
reqOptions.headers = {'Content-Type': 'multipart/form-data','Accept': 'application/json'};
reqOptions.formData = formData;
logger.debug('REQ_OPTIONS ', reqOptions, '\n');
request.post(reqOptions, function (err, response, body) {
if (err) {
removeFiles(TMP);
logger.warn(req, ' Error sending attachment', err);
res.status(400);
res.json({"msg": "Error sending attachment"});
} else {
removeFiles(TMP);
res.status(201);
logger.debug('BODY ', body);
res.send(body);
}
});
}
这个错误可能是错误消息完全误导的最好例子之一。所以。对该问题进行 RCA 非常令人沮丧:
ERROR: uncaught Exception: source.on is not a function
其实这里什么功能都没有。就我而言,我花了好几个小时摸不着头脑,最后才发现它是 JSON 在另一个 JSON 下面,这导致了这个错误:
let subJson =
{
field1: "value1",
field2: "value2"
}
let myJson =
{
field1: "value1",
field2: "value2",
field3: subJson
}
createFormData(myJson);
就是它了!当您使用 myJson
作为参数调用 createFormData
时,您将看到异常 source.on is not a function
!我们一直在想那个功能在哪里?
解决方案是JSON.stringify
field3: JSON.stringify(subJson)
将解决这个问题。
javascript!
我正在尝试将数据从我的节点应用程序发送到第 3 方 HTTP 端点。
我正在使用多方模块解析来自客户端的请求 object 上的数据,并通过请求模块发送数据。我收到错误
错误:未捕获异常:source.on 不是函数
var request = require('request');
const multiparty = require('multiparty');
function addAttachment(req, res) {
let form = new multiparty.Form();
let parsedFile = {};
const formData = {};
form.parse(req, function(err, fields, files){
Object.keys(fields).forEach(function(name) {
formData[name] = fields[name][0];
});
Object.keys(files).forEach(function(name) {
logger.debug(name);
parsedFile[name] = files[name][0];
});
formData.uploadFile = parsedFile.uploadFile;
logger.debug('formData ', formData);
reqOptions.url = imageURL;
reqOptions.formData = formData;
logger.debug('REQ_OPTIONS ', reqOptions);
request.post(reqOptions, function (err, response, body) {
if (err) {
logger.warn(req, ' Error sending attachment', err);
res.status(400);
res.json({ "msg": "Error sending attachment" });
} else {
res.status(201);
logger.debug('BODY ', body);
res.send(body);
}
});
});
}
reqOptions
obj包含headers、url、auth obj,我们再往里面添加表单数据。
当我记录表单数据时,它看起来格式正确
{
"meta": {
"prop1": "xxxxxx",
"prop2": "xxxxxxxxxxxxx",
"uploadFile": {
"fieldName": "uploadFile",
"originalFilename": "test.PNG",
"path": "/tmp/W1IppPiK04JpkPrnZWEhzkmV.PNG",
"headers": {
"content-disposition": "form-data; name=\"uploadFile\"; filename=\"test.PNG\"",
"content-type": "image/png"
},
"size": 42786
}
}
}
所以经过一些摸索和挖掘,我能够 post 向外部 API 形成数据。我决定将我使用的节点模块更改为 connect-multiparty
。 Connect 将解析请求 headers 并解码 post-form-data 允许您访问来自 req
obj 的数据 E.G req.body
现在具有添加的属性并且 req.files
具有上传的文件。
const multipart = require('connect-multiparty');
const multipartMiddleware = multipart();
然后将multipartMiddleware
添加到路由中。
app.post('/api/addAttachment' multipartMiddleware, MyController.addAttachment);
然后在我的控制器文件中,我将代码更改为使用 connect-multipart
。
const fs = require('fs');
var request = require('request');
function addAttachment(req, res) {
const TMP = '/tmp';
let formData = {};
Object.keys(req.body).forEach((propName) =>{
if (typeof propName === 'string') {
logger.debug(propName, ' is a string');
formData[propName] = req.body[propName];
} else {
logger.debug(propName, ' is not a string')
}
});
//The files get added to the tmp folder on the files system,
//So we create a stream to read from tmp folder,
//at the end end we need to delete the file
formData['uploadFile'] = fs.createReadStream(req.files.uploadFile.path);
logger.debug('FORM DATA ', formData, '\n');
reqOptions.url = imageUrl;
reqOptions.headers = {'Content-Type': 'multipart/form-data','Accept': 'application/json'};
reqOptions.formData = formData;
logger.debug('REQ_OPTIONS ', reqOptions, '\n');
request.post(reqOptions, function (err, response, body) {
if (err) {
removeFiles(TMP);
logger.warn(req, ' Error sending attachment', err);
res.status(400);
res.json({"msg": "Error sending attachment"});
} else {
removeFiles(TMP);
res.status(201);
logger.debug('BODY ', body);
res.send(body);
}
});
}
这个错误可能是错误消息完全误导的最好例子之一。所以。对该问题进行 RCA 非常令人沮丧:
ERROR: uncaught Exception: source.on is not a function
其实这里什么功能都没有。就我而言,我花了好几个小时摸不着头脑,最后才发现它是 JSON 在另一个 JSON 下面,这导致了这个错误:
let subJson =
{
field1: "value1",
field2: "value2"
}
let myJson =
{
field1: "value1",
field2: "value2",
field3: subJson
}
createFormData(myJson);
就是它了!当您使用 myJson
作为参数调用 createFormData
时,您将看到异常 source.on is not a function
!我们一直在想那个功能在哪里?
解决方案是JSON.stringify
field3: JSON.stringify(subJson)
将解决这个问题。
javascript!