简体   繁体   English

在不发送内容长度标头的情况下在Node中流数据

[英]Stream data in Node without sending content-length header

I have this function which streams buffered data: 我有此功能流缓冲的数据:

function doChunkInput() {
  console.log('Put Objects Chunk');
  let stream = new Readable({
    read() {}
  })

  for(i=0; i < 1000; i++) {
    stream.push(' data');
    stream.push(' more data');
    stream.push(' and more data');
  }

  // Pay attention to this
  // null indicates the end of the stream, so the `data` event will be fired
  stream.push(null)

  const params = {
    Bucket: bucket,
    Body: stream,
    Key: `sitemap.1.xml`,
  };
  return s3.upload(params).promise();

Is it possible to from a stream without buffering. 是否可以从流中不进行缓冲。 What I want is to stream data where the content-length can't be calculted. 我想要的是在无法计算内容长度的地方传输数据。 In the above example it is getting calculated in the buffer. 在上面的示例中,正在缓冲区中进行计算。

I'm trying to test the chunked upload but with the above example the content-length header is added to the request and the transfer-encoding header is not. 我正在尝试测试分块上载,但是在上面的示例中, content-length标头已添加到请求中,而transfer-encoding标头则未添加。

Short answer is no. 简短的答案是没有。 AWS SDK does not support streaming, but there's a nice way around it. AWS开发工具包不支持流传输,但是有很好的解决方法。

You can upload in parts of any size (mind you, as per anything AWS, you pay a tiny bit for each upload - lots of parts may grow to a visible cost). 您可以上传任意大小的部分(请注意,按照AWS的任何规定,每次上传都需要支付少量费用-很多部分可能会增加到可见的成本)。 There's even a nice npm module called: s3-stream-upload which exposes a normal Writable stream interface that you can pipe to. 甚至还有一个很好的npm模块,称为: s3-stream-upload ,它公开了您可以通过管道传输的常规Writable流接口。

You could use my scramjet if you'd prefer to have some special logic around the upload - it's actually quite simple: 如果您希望对上传内容有一些特殊的逻辑,可以使用我的scramjet -实际上很简单:

const { StringStream } = require("scramjet");

const params = {Key: 'filename', Bucket: 'my-bucket'};
const { UploadId } = await s3.createMultipartUpload(params).promise();
let i = 1;

StringStream
    .from(function*() {
        for(i=0; i < 1000; i++) {
           yield ' data';
           yield ' more data';
           yield ' and more data';
        }
    })
    .toBufferStream()
    .breakup(1048576)   // you'd buffer every 1meg
    .map(
        (Body) => s3.uploadPart({
            ...params,
            Body,
            UploadId,
            PartNumber: i++
        }).promise()
    )
    .toArray()
    .then(
        parts => s3.completeMultipartUpload({
            ...params,
            MultipartUpload: {
                Parts: parts.map(
                    ({ ETag }, i) => ({ ETag, PartNumber: i + 1 })
                )
            }
        }).promise()
    )
    .catch(
        e => {
            console.error("error, aborting", e);
            return s3.abortMultipartUpload({...params, UploadId})
        }
    )

I'm sorry - I didn't run the example above, so it's more of a guide what should happen - but I can fix up tomorrow if you get stuck. 抱歉-我没有运行上面的示例,因此更多地应该指导您进行操作-但如果您遇到问题,我明天可以解决。


edit: Now I understand that you want to know how to create a stream and add to it without building the whole stream upfront 编辑:现在,我了解到您想知道如何创建流并将其添加到流中而无需先构建整个流

I changed the answer above to create a stream from generator. 我更改了上面的答案以从生成器创建流。 You could also implement the read method in your example to return the 'data' via this.push ( see docs here ), but I guess it's way simpler with scramjet and generators. 您还可以在示例中实现read方法,以通过this.push返回“数据”( 请参阅此处的文档 ),但是我想使用this.push和generators会更简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM