C#做MD5并一次下载的有效方法是什么?

时间:2015-05-15 21:53:44

标签: c# download md5sum

我正在进行下载,然后进行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()

3 个答案:

答案 0 :(得分:7)

  

作为下载流的一部分,是否有一种良好,干净的计算MD5的方法?理想情况下,MD5应该脱离DownloadFile()函数作为排序的副作用。

您可以遵循此策略,进行“分块”计算并最大限度地减少内存压力(和重复):

  1. 在Web客户端上打开响应流。
  2. 打开目标文件流。
  3. 有可用数据时重复:
    • 从响应流中读取块到字节缓冲区
    • 将其写入目标文件流。
    • 使用TransformBlock方法将字节添加到哈希计算
  4. 使用TransformFinalBlock获取计算的哈希码。
  5. 下面的示例代码显示了如何实现这一目标。

    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);