从 Amazon AWS S3 下载对象时流仅部分读取

Stream only partially read when downloading object from Amazon AWS S3

我正在尝试使用 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 不是 public 属性,我无法在我的代码中访问它来创建 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();
    }
}

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

您也可以只循环直到返回值为 0,这意味着 error / no more bytes left

您将需要跟踪内容缓冲区的当前偏移量,以免每次调用都覆盖数据。