通过HTTP传输的文件仅部分写入

时间:2019-02-22 01:53:48

标签: javascript node.js http

我正在尝试使用NodeJS和Express通过HTTP传输二进制文件。该文件不是很大,但足够大,足以让我遇到麻烦(〜1.8 Mo)。

我正在使用fs.readFile(..)读取文件,然后使用内置的res.sendFile(..)函数发送文件。如果我执行curl命令并将其结果重定向到一个新文件,则原始文件的内容将完美地复制到服务器上,并且可以使用它。

但是,如果我使用NodeJs通过使用http模块和缓冲区来执行此操作,则仅写入文件的65.5 Ko。 我尝试使用curl-request模块,并将主体写入文件。它的工作效果略好一些,但仍然只将1.7 Mo复制到了新文件中,仍然不完整。

这是我用来发送文件的代码:

app.get('/global_model', (req, res, next) => {
    res.sendFile(__dirname+'/global-model/weights.bin');
});

以及接收它的代码(使用http模块):

  const options = {
          hostname: host,
          port: port,
          path: '/global_model',
          method: 'GET',
     };
      return new Promise((resolve, reject) => {
          const req = http.request(options, (res) => {
              res.on('data', (d) => {
                 let buffer = new Buffer(d, 'binary');
                 fs.writeFile(__dirname+'/loc-model/weights.bin', buffer, (err) => {
                     if(!err) {
                         resolve();
                     }
                 });
             });
          });
          req.on('error', (error) => {
              reject(error);
          });
          req.end();
      });

并使用curl-request模块:

let curl = new (require('curl-request'))();
    return new Promise(resolve => {
        curl.get('http://localhost:33333/global_model')
        .then(({statusCode, body, headers}) => {
            fs.writeFile(__dirname+'/loc-model/weights.bin', body, {encoding:'binary'} , (err) => {
                if(!err) {
                    resolve();
                }
            });

        });
    });

Wireshark显示在处理请求时没有损失。我对这个相对简单的任务有点迷茫。 我做错什么了吗?

编辑:我尝试在缓冲区上使用ReadStream,但仍然无法完全保存文件。

1 个答案:

答案 0 :(得分:0)

您的代码会在每个新的数据块上重写文件,并在收到新数据后立即解析。

您需要将HTTP读取流通过管道传输到文件中-像这样(未经测试,YMMV)。

const options = {
  hostname: host,
  port: port,
  path: "/global_model",
  method: "GET",
};
return new Promise((resolve, reject) => {
  const req = http.request(options, res => {
    const outStream = fs.createWriteStream(__dirname + "/loc-model/weights.bin");
    outStream.on("error", reject);
    res.pipe(outStream);
    res.on("end", () => {
      outStream.close();
      resolve();
    });
  });
  req.on("error", reject);
});