Я использую API для загрузки файла CSV. Я создаю CSV-файл в памяти из String и загружаю его с помощью модуля request. Однако у меня возникают проблемы с созданием потока для чтения из строки. Я последовал ТАК-ответу на Как создавать потоки из строки в Node.Js. Вот мой код для этого решения:
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.info(err || "Error status code: " + res.statusCode);
console.info(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.info(err || "Error status code: " + res.statusCode);
console.info(body);
return;
}
});
});
}
Как я могу преобразовать вывод stringify в поток, который я могу использовать для загрузки через api?
Похоже, csv-stringify может сам создавать потоки, к вашему сведению. Вероятно, вы можете просто передать stringify(csv) напрямую как "файловый" поток.
@Jacob ага, это исправило. Изменил свой код на var output = stringify(csv);, и теперь он работает. Также изменил модуль stringify на синхронный. Спасибо!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Образец фрагмента неверен или, возможно, устарел для текущих версий узла. Действительно простой способ реализовать ваш читаемый:
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);
}
}
});
Спасибо за реплики. Я попытался добавить ваш фрагмент вместо предыдущего, но все равно получил ту же ошибку Unexpected end of input.
Ой, я ошибся при сигнале EOF. Попробуй мое обновление.
Добавлены примечания по кодировке. Это странно.
Думаю, я понял это после того, как заметил, что вы используете request. Это странно с загрузкой "файлов". Смотрите другой ответ.
(оставим это пока на случай, если есть проблема с потоком, но, вероятно, это другой ответ).
Похоже, вы используете библиотеку request. Вы можете встретить это предостережение, как описано в их Прочти меня:
// 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.info(err || "Error status code: " + res.statusCode);
console.info(body);
return;
}
});
Привет, Джейкоб, я попытался добавить имя файла (оно было там ранее), но оно все равно не работает. Интересно, а в Stringify проблема. Я подумал, что, возможно, это был символ новой строки в конце строки, но это не так. Я не уверен, что это проблема с Stringify, а memfs «устраняет» проблему при сохранении, или если сам поток неправильный и не обязательно контент ... если это имеет смысл.
Да, это пакет. Извините должно было быть более ясным.
Просто чтобы мы знали наверняка, откуда берется
stringify? У вас есть конкретный пакет, который вам нужен?