从Amazon AWS S3下载对象时仅流部分读取[重复]

问题描述 投票:2回答:1

这个问题在这里已有答案:

我试图简单地使用C#从我的桶中下载一个对象,就像我们在S3示例中找到的那样,我无法弄清楚为什么流不会完全复制到我的字节数组中。仅复制前8192个字节而不是整个流。

我尝试过使用Amazon.S3.AmazonS3ClientAmazon.S3.Transfer.TransferUtility,但在这两种情况下,只有第一个字节实际上被复制到缓冲区中。

var stream = await _transferUtility.OpenStreamAsync(BucketName, key);
using (stream)
{
    byte[] content = new byte[stream.Length];
    stream.Read(content, 0, content.Length);
    // Here content should contain all the data from the stream, but only the first 8192 bytes are actually populated.
}

调试时,我看到流类型是Amazon.Runtime.Internal.Util.Md5Stream,并且在流内部,在调用Read()之前,属性CurrentPosition = 0.调用之后,CurrentPosition变为8192,这似乎确实表明只读取了前8K数据。该流的总Length是104042。

如果我对stream.Read()进行更多调用,我会看到更多数据被读取并且CurrentPosition值增加。但CurrentPosition不是公共财产,我无法在我的代码中访问它来制作一个while()循环(并且必须编写这样的循环来读取所有数据似乎有点笨拙)。

为什么我的代码中只读取了第一个8K?我该如何继续阅读整个流?

我试过调用stream.Flush(),但它没有解决问题。

编辑1

我修改了我的代码,因此它执行以下操作:

var stream = await _transferUtility.OpenStreamAsync(BucketName, key);
using (stream)
{
    byte[] content = new byte[stream.Length];
    var bytesRead = 0;

    while (bytesRead < stream.Length)
        bytesRead += stream.Read(content, bytesRead, content.Length - bytesRead);
}

它有效。但看起来仍然很笨重。我不得不这样做吗?

编辑2

最终的解决方案是创建一个正确大小的MemoryStream,然后调用CopyTo()。因此,如果Read()在读取整个流之前开始返回0,则不再有笨重的循环且没有无限循环的风险:

var stream = await _transferUtility.OpenStreamAsync(BucketName, key);
using (stream)
{
    using (var memoryStream = new MemoryStream((int)stream.Length))
    {
        stream.CopyTo(memoryStream);
        var myBuffer = memoryStream.GetBuffer();
    }
}
c# amazon-web-services amazon-s3 aws-sdk
1个回答
2
投票

stream.Read()返回读取的字节数。然后,您可以跟踪读取的总字节数,直到到达文件末尾(content.Length)。

您也可以循环,直到返回值为0表示error / no more bytes left

您需要跟踪内容缓冲区的当前偏移量,以便不覆盖每个调用的数据。

© www.soinside.com 2019 - 2024. All rights reserved.