使用 http post 流式传输二进制文件
Stream binary file with http post
我正在使用请求库在使用 http post 的请求正文中发送二进制 (pdf) 文件(注意:此 API 不接受多部分形式) .但是,我只能使用 fs.readFilesync()
让它工作。出于某种原因,当我尝试使用 fs.createReadStream()
时,pdf 文件仍会发送,但它是空的,并且请求永远不会完成(我从来没有从服务器得到响应)。
这是我使用 fs.readFileSync()
:
的工作版本
const request = require('request');
const fs = require('fs');
const filename = 'test.pdf';
request({
url: 'http://localhost:8083/api/v1/endpoint',
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'Accept': 'application/vnd.api+json',
'Content-Disposition': `file; filename="${filename}"`
},
encoding: null,
body: fs.readFileSync(filename)
}, (error, response, body) => {
if (error) {
console.log('error:', error);
} else {
console.log(JSON.parse(response.body.toString()));
}
});
如果我尝试用下面的替换主体,它不起作用:
body: fs.createReadStream(filename)
我也试过将 http 请求通过管道传输到流中,就像请求库文档中所说的那样,但我得到了相同的结果:
fs.createReadStream(filename).pipe(request({...}))
我尝试通过执行以下操作来监控流:
var upload = fs.createReadStream('test.pdf');
upload.pipe(req);
var upload_progress = 0;
upload.on("data", function (chunk) {
upload_progress += chunk.length
console.log(new Date(), upload_progress);
})
upload.on("end", function (res) {
console.log('Finished');
req.end();
})
我看到了流和 Finished
的进展,但仍然没有从 API 返回任何响应。
我更愿意创建一个读取流,因为这样可以更好地处理更大的文件,但我不知道出了什么问题。我确保我也没有使用任何特殊编码更改文件。
有什么方法可以获取某种输出以查看哪个进程一直在运行?
更新:
我决定用一个简单的 1 KB .txt
文件进行测试。我发现使用fs.createReadStream()
它仍然是空的,但是,这次我得到了服务器的响应。我正在使用的测试 PDF 是 363 KB,大小不算离谱,但仍然...... 无论如何,流不是为大文件制作的吗?使用 fs.readFileSync()
也适用于文本文件。
我开始怀疑这是同步还是异步问题。我知道 fs.readFileSync()
是同步的。我是否需要等到 fs.createReadStream()
完成后再尝试将其附加到正文?
我可以通过执行以下操作来实现此功能:
const request = require('request');
const fs = require('fs');
const filename = 'test.pdf';
const readStream = fs.createReadStream(filename);
let chunks = [];
readStream.on('data', (chunk) => chunks.push(chunk));
readStream.on('end', () => {
const data = Buffer.concat(chunks);
request({
url: 'http://localhost:8083/api/v1/endpoint',
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'Accept': 'application/vnd.api+json',
'Content-Disposition': `file; filename="${filename}"`
},
encoding: null,
body: data
}, (error, response, body) => {
if (error) {
console.log('error:', error);
} else {
console.log(JSON.parse(response.body.toString()));
}
});
});
在发出请求之前,我将数据分块并与缓冲区连接。
我在 the documentation 中注意到它是这样说的:
The Buffer class was introduced as part of the Node.js API to enable interaction with octet streams in TCP streams, file system operations, and other contexts.
我正在调用的 API 需要 application/octet-stream
header,所以我需要使用缓冲区而不是直接流式传输它。
我正在使用请求库在使用 http post 的请求正文中发送二进制 (pdf) 文件(注意:此 API 不接受多部分形式) .但是,我只能使用 fs.readFilesync()
让它工作。出于某种原因,当我尝试使用 fs.createReadStream()
时,pdf 文件仍会发送,但它是空的,并且请求永远不会完成(我从来没有从服务器得到响应)。
这是我使用 fs.readFileSync()
:
const request = require('request');
const fs = require('fs');
const filename = 'test.pdf';
request({
url: 'http://localhost:8083/api/v1/endpoint',
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'Accept': 'application/vnd.api+json',
'Content-Disposition': `file; filename="${filename}"`
},
encoding: null,
body: fs.readFileSync(filename)
}, (error, response, body) => {
if (error) {
console.log('error:', error);
} else {
console.log(JSON.parse(response.body.toString()));
}
});
如果我尝试用下面的替换主体,它不起作用:
body: fs.createReadStream(filename)
我也试过将 http 请求通过管道传输到流中,就像请求库文档中所说的那样,但我得到了相同的结果:
fs.createReadStream(filename).pipe(request({...}))
我尝试通过执行以下操作来监控流:
var upload = fs.createReadStream('test.pdf');
upload.pipe(req);
var upload_progress = 0;
upload.on("data", function (chunk) {
upload_progress += chunk.length
console.log(new Date(), upload_progress);
})
upload.on("end", function (res) {
console.log('Finished');
req.end();
})
我看到了流和 Finished
的进展,但仍然没有从 API 返回任何响应。
我更愿意创建一个读取流,因为这样可以更好地处理更大的文件,但我不知道出了什么问题。我确保我也没有使用任何特殊编码更改文件。
有什么方法可以获取某种输出以查看哪个进程一直在运行?
更新:
我决定用一个简单的 1 KB .txt
文件进行测试。我发现使用fs.createReadStream()
它仍然是空的,但是,这次我得到了服务器的响应。我正在使用的测试 PDF 是 363 KB,大小不算离谱,但仍然...... 无论如何,流不是为大文件制作的吗?使用 fs.readFileSync()
也适用于文本文件。
我开始怀疑这是同步还是异步问题。我知道 fs.readFileSync()
是同步的。我是否需要等到 fs.createReadStream()
完成后再尝试将其附加到正文?
我可以通过执行以下操作来实现此功能:
const request = require('request');
const fs = require('fs');
const filename = 'test.pdf';
const readStream = fs.createReadStream(filename);
let chunks = [];
readStream.on('data', (chunk) => chunks.push(chunk));
readStream.on('end', () => {
const data = Buffer.concat(chunks);
request({
url: 'http://localhost:8083/api/v1/endpoint',
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'Accept': 'application/vnd.api+json',
'Content-Disposition': `file; filename="${filename}"`
},
encoding: null,
body: data
}, (error, response, body) => {
if (error) {
console.log('error:', error);
} else {
console.log(JSON.parse(response.body.toString()));
}
});
});
在发出请求之前,我将数据分块并与缓冲区连接。
我在 the documentation 中注意到它是这样说的:
The Buffer class was introduced as part of the Node.js API to enable interaction with octet streams in TCP streams, file system operations, and other contexts.
我正在调用的 API 需要 application/octet-stream
header,所以我需要使用缓冲区而不是直接流式传输它。