我正在尝试从节点服务器向api that expects a file and other form data as an multipart/form-data发送发布请求。
这是我的代码的样子
var importResponse = function(csv){
stringify(csv, function(err, output){
request.post({
headers: {'X-API-TOKEN':token, 'content-type' : 'multipart/form-data'},
url: url,
formData: {
surveyId: surveyId,
file: {
value: output,
options: {
fileName: 'test.csv',
contentType:'text/csv'
}
}
}
}, function(error, response, body){
console.log(body);
});
});
}
使用request-debug
是请求:
request:
{ debugId: 1,
uri: 'https://co1.qualtrics.com/API/v3/responseimports',
method: 'POST',
headers:
{ 'X-API-TOKEN': 'removed',
'content-type':
'multipart/form-data; boundary=--------------------------010815605562947295265820',
host: 'co1.qualtrics.com',
'content-length': 575 } } }
和响应:
response:
{ debugId: 1,
headers:
{ 'content-type': 'application/json',
'content-length': '188',
'x-edgeconnect-midmile-rtt': '28',
'x-edgeconnect-origin-mex-latency': '56',
date: 'Wed, 18 Jul 2018 03:57:59 GMT',
connection: 'close',
'set-cookie': [Array],
'strict-transport-security': 'max-age=31536000; includeSubDomains; preload' },
statusCode: 400,
body:
'{"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Missing Content-Type for file part. name=file","errorCode":"MFDP_3"},"requestId":"322a16db-97f4-49e5-bf10-2ecd7665972e"}}' } }
我得到的错误是:Missing Content-Type for file part.
我已经在选项中添加了它:
options: {
fileName: 'test.csv',
contentType:'text/csv'
}
当我查看请求时,似乎没有包含表单数据。但这也许只是request-debug
没有显示出来。
我看到了类似的SO question,答案是使用JSON.stringify
。
我尝试将代码更改为以下内容:
request.post({
headers: {'X-API-TOKEN':token, 'content-type' : 'multipart/form-data'},
url: url,
body: JSON.stringify({
surveyId: surveyId,
file: {
value: output,
options: {
fileName: 'test.csv',
contentType:'text/csv'
}
}
})
但是,出现以下错误:
{"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Missing boundary header"}}}
我在做什么错了?
更新
当我尝试在计算机fs.createReadStream('test.csv')
上将文件值更改为csv时,效果很好
file: {
value: fs.createReadStream('test.csv'),
options: {
contentType: 'text/csv'
}
}
所以我认为我给文件的方式出了问题。我用作文件的output
变量看起来像"QID1,QID2\nQID1,QID2\n1,2"
。我认为这是导致问题的原因,即使错误有点误导。我尝试创建一个StackOverFlow answer的Readable
,如下所示:
var s = new Readable
s.push(output)
s.push(null)
但是,这导致了Unexpected end of input
{"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Unexpected end of input"}}}
答案 0 :(得分:2)
嘿,埃里克(Eric)检查了他们接受multipartRequest的格式,就像我将文件上传到驱动器上一样:
request(options, function (err, response) {
var boundary = '-------314159265358979323846';
var delimiter = "\r\n--" + boundary + "\r\n";
var close_delim = "\r\n--" + boundary + "--";
var fileContent = 'Sample upload :)';
var metadata = {
'name': 'myFile.txt',
'mimeType': 'text/plain\r\n\r\n'
};
var multipartRequestBody = delimiter + 'Content-Type: application/json\r\n\r\n' + JSON.stringify(metadata) + delimiter + 'Content-Type: ' + 'text/plain\r\n\r\n' + fileContent + close_delim;
request(options, function (err, response) {
var url = 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&access_token=' + JSON.parse(response.body).access_token;
var options = {
method: 'POST',
url: url,
headers: {
'Content-Type': 'multipart/related; boundary="' + boundary + '"'
},
body: multipartRequestBody
};
request(options, function (err, response) {
res.send({resultdata: response.body});
});
});
});
根据您的端点接受设置多部分。
答案 1 :(得分:1)
是否可能为文件使用了错误的属性名称?
快速阅读request
节点模块的表单信息使我认为您应该使用custom_file
而不是file
。
您可以在此处了解更多信息:https://github.com/request/request#forms
答案 2 :(得分:1)
我发现了问题。我的第一个解决方案很好,但应该是fileName
filename
var importResponse = function(csv){
stringify(csv, function(err, output){
request.post({
headers: {'X-API-TOKEN':token, 'content-type' : 'multipart/form-data'},
url: url,
formData: {
surveyId: surveyId,
file: {
value: output,
options: {
filename: 'test.csv', //filename NOT fileName
contentType:'text/csv'
}
}
}
}, function(error, response, body){
console.log(body);
});
});
}
答案 3 :(得分:0)
使用诸如express(它们自动解析标头和响应)之类的框架以及诸如multer之类的npm模块来处理多部分表单数据有助于使它们为您完成所有繁重的工作