【问题标题】:Custom MD5 / CRC check for a re downloaded ftp always saying the file is different from the original自定义 MD5 / CRC 检查重新下载的 ftp 总是说文件与原始文件不同
【发布时间】:2015-10-29 07:54:22
【问题描述】:

我正在将文件 uloading 到 ftp 并且需要确保文件被正确传输。为此,我随后重新下载文件并检查文件是否与原始本地文件内容相同。为此,我以小块的形式读取每个文件并在内容上生成 MD5 和。

尽管 MD5 可以表示的内容有限,但我认为就查看文件是否存在差异而言(通常最大为 2 MB)就足够了。现在,虽然当我为每个流(一个是下载流,另一个是本地文件读取流)生成 MD5 时,我遇到了一个问题,即两者的 MD5 不同(尽管前几个块在MD5。并且文件本身是一个 zip 文件,可以在 ftp 服务器上毫无问题地提取)。

我想知道的是:我的想法本身是否有错误?或者我的代码有错误吗?或者为什么内容看起来不同?

电话:

ftpMD5 = GeneriereMD5FuerStream(ftpAnsuchen.GetResponse().GetResponseStream());
lokalMD5 = GeneriereMD5FuerStream((new FileInfo(lokaleDateiPfad)).OpenRead());

if (ftpMD5.Equals(lokalMD5) == false)
{
    throw exception "Different";
}

方法代码:

    private string GeneriereMD5FuerStream(Stream leseStream)
    {
        string md5String = String.Empty;
        byte[] leseBuffer = new byte[2048];
        int bytesGelesen = 0;
        MD5 md5Converter = MD5.Create();

        bytesGelesen = leseStream.Read(leseBuffer, 0, leseBuffer.Length);
        md5String = BitConverter.ToString(md5Converter.ComputeHash(Encoding.Default.GetBytes(md5String + BitConverter.ToString(md5Converter.ComputeHash(leseBuffer)))));

        while (bytesGelesen > 0)
        {
            bytesGelesen = leseStream.Read(leseBuffer, 0, leseBuffer.Length);

            if (bytesGelesen > 0) 
            {
                md5String = BitConverter.ToString(md5Converter.ComputeHash(Encoding.Default.GetBytes(md5String + BitConverter.ToString(md5Converter.ComputeHash(leseBuffer)))));
            }
        }

        return md5String;
    }

【问题讨论】:

  • 同时我通过使用 return BitConverter.ToString((MD5.Create()).ComputeHash(leseStream));但我仍然会对手动创建 MD5 失败的原因感兴趣。
  • 是的,您计算哈希的方式意味着哈希将根据块的大小而有所不同。

标签: c# ftp


【解决方案1】:

我强烈建议下载整个文件并对整个文件内容执行哈希处理。

正如基思所说,您不能保证您的缓冲区将包含一组值,因为网络延迟可能会产生问题。另一种方法是不基于缓冲区以设置的字节间隔计算 md5 哈希值,但最终还是要下载整个文件,所以从头开始做。

MD5.ComputeHash 还有一个你应该使用的流重载。

https://msdn.microsoft.com/en-us/library/system.security.cryptography.md5(v=vs.110).aspx

【讨论】:

    【解决方案2】:

    您计算 MD5 的方式对读入缓冲区的字节数很敏感。

    看这一行:

    bytesGelesen = leseStream.Read(leseBuffer, 0, leseBuffer.Length);
    

    对于文件,在读取最后一个块之前,bytesGelesen 将始终为 leseBuffer.Length

    对于网络流,bytesGelesen 可能不是 leseBuffer 的完整大小。

    您有两个选择,将文件从网络流读取到磁盘,然后使用您当前对该文件的方法来计算哈希(以确保每次读取迭代时读取的字节的一致性)或更改您的哈希计算这样无论每次调用 read 时读取的字节长度如何,它都会返回相同的值。

    为了证明我的理论,只需在从 FTP 服务器拉取文件时写出 bytesGelesen 并与从磁盘读取文件时进行比较。

    【讨论】:

    • 啊,所以你的意思是,尽管文件相同,但如果 ftp 之间的速度有点太慢,那么从 ftp 下载的数据块最终可能会出现不同大小的块,因此再次发送的次数越来越少,.. . ?
    【解决方案3】:

    在您的情况下是否有必要计算哈希?我想还有另一种方法可以检查文件是否已传输。您可以基于BackgroundWorker 并在上传文件时监控进度。有人描述了它HERE

    【讨论】:

    • 例如,当我使用工具传输 100 MB zip 文件时,我没有收到任何错误,文件在那里但已损坏(也就是不可提取)。哈希的想法源于这种情况,因此我检查文件是否正确(即使在重新下载期间它可能被损坏,最好说一次“错误”,而不是在我的情况下少说一次)。所以是的,我担心有必要检查 ftp 和本地上的所有字节是否相同。唯一的问题是这是否是正确的方法,如果是,为什么我的代码会失败。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 2020-09-30
    • 2017-05-30
    相关资源
    最近更新 更多