这个问题在这里已有答案:
我试图简单地使用C#从我的桶中下载一个对象,就像我们在S3示例中找到的那样,我无法弄清楚为什么流不会完全复制到我的字节数组中。仅复制前8192个字节而不是整个流。
我尝试过使用Amazon.S3.AmazonS3Client
和Amazon.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();
}
}
stream.Read()
返回读取的字节数。然后,您可以跟踪读取的总字节数,直到到达文件末尾(content.Length
)。
您也可以循环,直到返回值为0表示error
/ no more bytes left
。
您需要跟踪内容缓冲区的当前偏移量,以便不覆盖每个调用的数据。