ahs*_*ele 5 c# md5 filestream async-await asp.net-core
我正在构建一个ASP.NET核心应用程序,它需要处理大量文件上传 - 高达200GB.我的目标是将这些文件写入磁盘并同时捕获MD5哈希.
我已经完成并创建了自己的方法来识别来自HTTP客户端请求的文件流,如上传带有流的大文件中所述.一旦我找到了流,我使用下面的代码写入磁盘并创建MD5哈希.
// removed the curly brackets from using statements for readability on Stack Overflow
var md5 = MD5.Create();
using (var targetStream = File.OpenWrite(pathAndFileName))
using (var cryptoStream = new CryptoStream(targetStream, md5, CryptoStreamMode.Write))
using (var sourceStream = fileNameAndStream.FileStream)
{
await sourceStream.CopyToAsync(cryptoStream);
}
var hash = md5.Hash;
md5.Dispose();
Run Code Online (Sandbox Code Playgroud)
什么是令人敬畏的是上述工作(文件创建和哈希生成).什么不是那么棒,我不完全理解这是如何工作的:
cryptoStream被复制,然后写入targetStream?cryptoStream字节保存在内存中还是只是随着它们读取它们?cryptoStream和targetStream异步发生?cryptoStream和同步写入targetStream?我很高兴这有效,但如果没有完全理解它,我担心我引入了一些邪恶的东西.
它的工作原理如下:
1)CopyToAsync分配指定大小的字节缓冲区(如果使用像问题那样的重载,则使用默认大小).然后它调用ReadAsync源流来填充该缓冲区,然后调用WriteAsync目标流将该缓冲区写入目标流.重复,直到写入所有数据.因此,此操作在内存中保存小字节数组(缓冲区).读写是异步的(如果源\目标流支持).
2)CryptoStream在写模式下的工作原理是这样的:当你写它,它需要缓冲你写(这是与上述相同的缓冲液),并且将其以ICryptoTransformimplementaiton你传递给它(在这种情况下- MD5).转换可能需要以特定大小的块(由ICryptoTransform.InputBlockSize属性确定)进行处理.在这种情况下,CryptoStream可能会缓存您写入的数据,直到存在特定大小的完整块.这不是问题,因为这些块通常非常小(远小于合理的缓冲区大小CopyAsync).然后它将ICryptoTransform.TransformBlock逐个传递这些块,并接收输出(另一个字节数组).这个过程是同步的,因为这里没有什么可以是异步的.
3)块转换后ICryptoTransform- 将此块targetStream异步(使用WriteAsync)写入输出流(在本例中).因此内存消耗CryptoStream也很小,并且与目标转换输入和输出块大小有关.
4)MD5实现ICryptoTransform使用传递块来连续计算哈希,因为该算法不需要立即存在完整数据来计算哈希值,它可以逐块计算它.然后输出与输入端接收的完全相同的块,因此不会进行转换.这意味着TransformBlockMD5只是按原样返回输入,同时在内部更新哈希.
总结并回答您的问题:
附注 - 要真正利用异步文件IO - 您需要使用"异步"选项初始化文件流,例如:
new FileStream(pathAndFileName, FileMode.Create, FileAccess.Write, FileShare.None,
4096, FileOptions.Asynchronous)
Run Code Online (Sandbox Code Playgroud)
否则,即使WriteAsync使用,您对目标流的写入也将是同步的.
| 归档时间: |
|
| 查看次数: |
398 次 |
| 最近记录: |