node.js - 使用 http post 流式传输二进制文件

标签 node.js node-request

我正在使用请求库通过 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();
})

我看到流的进度并已完成,但 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 ,因此我需要使用缓冲区而不是直接流式传输。

关于node.js - 使用 http post 流式传输二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59022685/

相关文章:

node.js - 触发 GET 请求并获取 Node Stream

node.js - 将上传的文件流式传输到 HTTP 请求

javascript - 为什么reduce中的predicate函数需要wrapper函数?

node.js - Nodejs 中的依赖注入(inject)模型

javascript - 为 Jest 测试设定时间目标

node.js - 两级嵌套 Mongoose 模式

node.js - 无法使用自定义 Materialise Sass 文件和 GruntJs 覆盖 node_modules 中的 Sass 变量

node.js - 执行 https 请求时出现 CERT_UNTRUSTED 错误

javascript - 如何使用 Node 请求发送不记名 token 和 x-www-form-urlencoded 数据

node.js - 如何使用node.js httpRequest连接到dashdb