我正在使用API to upload a CSV file。我从字符串在内存中创建CSV文件,然后使用request
模块上载它。但是,从字符串创建可读流时遇到了麻烦。我在How to create streams from string in Node.Js上回答了SO。这是该解决方案的代码:
var importResponse = function(csv, callback){
stringify(csv, function(err, output){
const s = new Readable();
s._read = () => {};
s.push(output);
s.push(null);
request.post({
headers: {'X-API-TOKEN':token, 'content-type' : 'multipart/form-data'},
url: 'https://ca1.qualtrics.com/API/v3/responseimports',
formData: {
surveyId: 'SV_123',
file: {
value: s,
options: {
contentType: 'text/csv; charset=utf-8'
}
}
}
}, function(err, res, body){
if(err || res.statusCode !== 200){
console.log(err || "Error status code: " + res.statusCode);
console.log(body);
return;
}
});
});
}
csv
变量类似于[["QID1","QID2"],["1","2"]]
,而stringify的输出类似于"QID1,QID2\n,1,2\n"
。
此解决方案给我错误Unexpected end of input
{"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Unexpected end of input"}}}
如果我改用memfs
,则效果很好
const fs = require('memfs');
var importResponse = function(csv, callback){
stringify(csv, function(err, output){
// Create file in memory
fs.writeFileSync('/data.csv', output);
request.post({
headers: {'X-API-TOKEN':token, 'content-type' : 'multipart/form-data'},
url: 'https://ca1.qualtrics.com/API/v3/responseimports',
formData: {
surveyId: 'SV_123',
file: {
value: fs.createReadStream('/data.csv'),
options: {
contentType: 'text/csv; charset=utf-8'
}
}
}
}, function(err, res, body){
if(err || res.statusCode !== 200){
console.log(err || "Error status code: " + res.statusCode);
console.log(body);
return;
}
});
});
}
如何将stringify
的输出转换为可用于通过api上传的流?
答案 0 :(得分:0)
该示例代码段不正确,或者对于当前节点版本而言可能已过时。实现可读性的一种非常简单的方法:
const s = new Readable({
encoding: 'utf8',
read(size) {
// Possibly respect the requested size to make for a good consumer experience
// Otherwise:
this.push(output, 'utf8');
this.push(null); // This signals that there's no more data.
}
});
您可以按照以下方式尊重读者的意愿:
let data = output;
const s = new Readable({
encoding: 'utf8',
read(size) {
let wantsMore = true;
while (wantsMore) {
const chunk = data.slice(0, size);
if (!chunk) {
return void this.push(null);
}
wantsMore = this.push(chunk, 'utf8');
data = data.slice(size);
}
}
});
答案 1 :(得分:0)
您似乎正在使用request
库。您可能会遇到他们的readme中记录的警告:
// Pass optional meta-data with an 'options' object with style: {value: DATA, options: OPTIONS}
// Use case: for some types of streams, you'll need to provide "file"-related information manually.
// See the `form-data` README for more information about options: https://github.com/form-data/form-data
custom_file: {
value: fs.createReadStream('/dev/urandom'),
options: {
filename: 'topsecret.jpg',
contentType: 'image/jpeg'
}
}
由于您使用的是非文件流,因此只需提供一个虚拟文件名即可:
request.post({
headers: {'X-API-TOKEN':token, 'content-type' : 'multipart/form-data'},
url: 'https://ca1.qualtrics.com/API/v3/responseimports',
formData: {
surveyId: 'SV_123',
file: {
value: s,
options: {
contentType: 'text/csv; charset=utf-8',
filename: 'dummy.csv'
}
}
}
}, function(err, res, body){
if(err || res.statusCode !== 200){
console.log(err || "Error status code: " + res.statusCode);
console.log(body);
return;
}
});