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

时间:2018-09-06 18:15:12

标签: c# amazon-web-services amazon-s3 aws-sdk

我正尝试使用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();
    }
}

1 个答案:

答案 0 :(得分:2)

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

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

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