我正在进行下载,然后进行MD5检查以确保下载成功。我有以下代码应该可以工作,但不是最有效的 - 特别是对于大文件。
raise_notrace
我担心的是所有字节都流式传输到磁盘,然后MD5 using (var client = new System.Net.WebClient())
{
client.DownloadFile(url, destinationFile);
}
var fileHash = GetMD5HashAsStringFromFile(destinationFile);
var successful = expectedHash.Equals(fileHash, StringComparison.OrdinalIgnoreCase);
必须打开文件并再次读取所有字节。有没有一种好的,干净的方式来计算MD5作为下载流的一部分?理想情况下,MD5应该脱离ComputeHash()
函数作为排序的副作用。具有如下签名的函数:
DownloadFile()
修改:添加string DownloadFileAndComputeHash(string url, string filename, HashTypeEnum hashType);
GetMD5HashAsStringFromFile()
答案 0 :(得分:7)
作为下载流的一部分,是否有一种良好,干净的计算MD5的方法?理想情况下,MD5应该脱离
DownloadFile()
函数作为排序的副作用。
您可以遵循此策略,进行“分块”计算并最大限度地减少内存压力(和重复):
TransformBlock
方法将字节添加到哈希计算TransformFinalBlock
获取计算的哈希码。下面的示例代码显示了如何实现这一目标。
public static byte[] DownloadAndGetHash(Uri file, string destFilePath, int bufferSize)
{
using (var md5 = MD5.Create())
using (var client = new System.Net.WebClient())
{
using (var src = client.OpenRead(file))
using (var dest = File.Create(destFilePath, bufferSize))
{
md5.Initialize();
var buffer = new byte[bufferSize];
while (true)
{
var read = src.Read(buffer, 0, buffer.Length);
if (read > 0)
{
dest.Write(buffer, 0, read);
md5.TransformBlock(buffer, 0, read, null, 0);
}
else // reached the end.
{
md5.TransformFinalBlock(buffer, 0, 0);
return md5.Hash;
}
}
}
}
}
答案 1 :(得分:1)
如果您正在谈论大文件(我假设超过1GB),您将需要以块的形式读取数据,然后通过MD5算法处理每个块,然后将其存储到磁盘。它是可行的,但我不知道有多少默认的.NET类可以帮助你。
一种方法可能是使用自定义流包装器。首先,您从WebClient获得Stream
(通过GetWebResponse()
然后GetResponseStream()
),然后将其换行,然后将其传递给ComputeHash(stream)
。当MD5在您的包装器上调用Read()
时,包装器将在网络流上调用Read
,在收到数据时将数据写出,然后将其传递回MD5。
如果您尝试这样做,我不知道会有什么问题等待您。
答案 2 :(得分:0)
像这样。
byte[] result;
using (var webClient = new System.Net.WebClient())
{
result = webClient.DownloadData("http://some.url");
}
byte[] hash = ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(result);