Как мне прикрепить файл в POST-запросе Node или Node Fetch? Я пытаюсь вызвать API, который будет импортировать файл CSV или XLS. Возможно ли это с помощью Node или Node Fetch?
Как отправить файл в запросе node-fetch или Node?
Ответ 1
README.md
говорит:
Используйте собственный поток для тела, как для запроса, так и для ответа.
И источники указывают, что он поддерживает несколько типов, например Stream
, Buffer
, Blob
... и также попытается coerce как String
для других типов.
Ниже фрагмента показаны 3 примера, все работают с v1.7.1 или 2.0.0-alpha5 (см. также другой пример далее с FormData
):
let fetch = require('node-fetch');
let fs = require('fs');
const stats = fs.statSync("foo.txt");
const fileSizeInBytes = stats.size;
// You can pass any of the 3 objects below as body
let readStream = fs.createReadStream('foo.txt');
//var stringContent = fs.readFileSync('foo.txt', 'utf8');
//var bufferContent = fs.readFileSync('foo.txt');
fetch('http://httpbin.org/post', {
method: 'POST',
headers: {
"Content-length": fileSizeInBytes
},
body: readStream // Here, stringContent or bufferContent would also work
})
.then(function(res) {
return res.json();
}).then(function(json) {
console.log(json);
});
Вот foo.txt
:
hello world!
how do you do?
Примечание. http://httpbin.org/post
отвечает с помощью JSON, который содержит детали отправки запроса.
Результат:
{
"args": {},
"data": "hello world!\nhow do you do?\n",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip,deflate",
"Connection": "close",
"Content-Length": "28",
"Host": "httpbin.org",
"User-Agent": "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)"
},
"json": null,
"origin": "86.247.18.156",
"url": "http://httpbin.org/post"
}
Если вам нужно отправить файл как часть формы с большим количеством параметров, вы можете попробовать:
-
npm install form-data
- передать объект
FormData
как тело (FormData
является видомStream
, черезCombinedStream
библиотека) - не пропускайте
header
в параметрах (в отличие от приведенных выше примеров)
а затем это работает:
const formData = new FormData();
formData.append('file', fs.createReadStream('foo.txt'));
formData.append('blah', 42);
fetch('http://httpbin.org/post', {
method: 'POST',
body: formData
})
Результат (просто показывая, что отправлено):
----------------------------802616704485543852140629
Content-Disposition: form-data; name="file"; filename="foo.txt"
Content-Type: text/plain
hello world!
how do you do?
----------------------------802616704485543852140629
Content-Disposition: form-data; name="blah"
42
----------------------------802616704485543852140629--
Ответ 2
Я искал, как использовать node-fetch
для загрузки файлов через multipart/form-data
, и их документы GitHub фактически показывают, как это сделать. Ниже приведен модифицированный пример, показывающий, как прикрепить буфер к FormData
и загрузить его.
const FormData = require('form-data');
const form = new FormData();
const buffer = // e.g. 'fs.readFileSync('./fileLocation');
const fileName = 'test.txt';
form.append('file', buffer, {
contentType: 'text/plain',
name: 'file',
filename: fileName,
});
fetch('https://httpbin.org/post', { method: 'POST', body: form })
.then(res => res.json())
.then(json => console.log(json));
Делюсь этим с кем-то еще, кто гуглил "node-fetch upload file multipart", как я.
Ответ 3
Это экспресс-сервер, который передает локальный файл в ответ.
var fs = require('fs');
var express = require('express')();
express.get('/',function(req,res){
var readStream = fs.createReadStream('./package.json');
readStream.pipe(res);
})
express.listen(2000);
Ответ 4
Есть одна вещь, чтобы добавить к Hugues M. ответ. Загрузка файла с помощью FormData
не поддерживается node-fetch
. Вместо этого вам нужно использовать другие библиотеки, такие как request
или request-promise
. Ниже приведен фрагмент кода для загрузки файла с использованием библиотеки request-promise
. resolveWithFullResponse
дает необработанный ответ. Без этого обещание возвращает только тело ответа.
let rp = require('request-promise')
var formData = {
file: fs.createReadStream('foo.txt'),
}
let options = {
uri:'http://httpbin.org/post',
formData: formData,
resolveWithFullResponse: true
}
rp.post(options).then((response) => {
// handle response here
})