对重新下载的ftp进行自定义MD5/CRC检查,总是说文件与原始文件不同
本文关键字:文件 检查 CRC 原始 MD5 下载 新下载 自定义 ftp | 更新日期: 2023-09-27 18:19:47
我正在将文件加载到ftp,需要确保文件传输正确。为此,我稍后将重新下载该文件,并检查该文件是否与原始本地文件内容相同。为了做到这一点,我以小块的形式读取每个文件,并在内容上生成MD5和。
尽管MD5的代表性有限,但我认为就查看文件(通常大小高达2MB)是否存在差异而言,它已经足够了。现在,当我为每个流(一个是下载流,另一个是lokal文件读取流)生成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;
}
我强烈建议下载整个文件并对整个文件内容执行哈希。
正如keith所提到的,您不能保证您的缓冲区将包含一组值,因为网络延迟可能会成为一个问题。另一种方法是以设置的字节间隔计算md5散列,而不是基于缓冲区,但最后你会下载整个文件,所以从头开始就这样做。
MD5.ComputeHash还有一个应该使用的流重载。
https://msdn.microsoft.com/en-us/library/system.security.cryptography.md5(v=vs.110).aspx
计算MD5的方式对读入缓冲区的字节数很敏感。
看看这条线:
bytesGelesen = leseStream.Read(leseBuffer, 0, leseBuffer.Length);
对于文件,在读取最后一个块之前,bytesGelesen将始终为leseBuffer.Length。
对于网络流,bytesGelesen可能不是leseBuffer的完整大小。
您有两个选项,将文件从网络流读取到磁盘,然后在此文件上使用当前的新方法来计算哈希(以确保每次读取迭代读取的字节的一致性)或更改哈希计算,使其返回相同的值,而不管每次读取调用读取的字节长度如何。
为了证明我的理论,当从FTP服务器提取文件时,只需写出bytesGelesen,并与从磁盘读取文件时进行比较。
在您的情况下有必要计算哈希吗?我想还有另一种方法可以检查文件是否已传输。您可以基于BackgroundWorker
并在上传文件时监控进度。有人在这里描述过。