通过网路上传或下载文件时,需要对文件进行验证是否传输正确,这可以通过MD5码实现。
不同的文件产生的MD5码是不同的,并且MD5码的计算是不可逆的。
假设要通过网络传输一个文件,在传输之前先计算出MD5码,将文件和MD5码一起发送出去。
接收端收到文件和MD5码以后,对文件再次计算MD5码,若两个MD5码相同证明文件传输正确。
具体计算方法:
/// <summary>
/// /// 计算文件的MD5校验/// /// </summary>
/// /// <param name="fileName">文件路径</param>
/// <returns>MD5码</returns>
private string GetMD5HashFromFile(string fileName)
{
try
{
FileStream file = new FileStream(fileName, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(file); //ComputeHash可按固定大小字节进行,这样就可以报告进度
//md5 .
file.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
catch (Exception ex)
{
throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
}
}
若文件比较大如1G 2G计算文件的过程会比较长 若希望得到MD5码的计算进度,可以用下面这种分块计算的方法,
块的大小自己根据需要调节,每计算完一块向外汇报一次进度即可。
/// <summary>/// 分块计算MD5码
/// </summary>
/// <param name="filename">文件路径</param>
/// <returns>MD5码</returns>
private string GetMD5HashFromFilePart(string filename)
{
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
int bufferSize = 1048576; // 缓冲区大小,1MB
byte[] buff = new byte[bufferSize];
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
md5.Initialize();
long offset = 0;
while (offset < fs.Length)
{
long readSize = bufferSize;
if (offset + readSize > fs.Length)
{
readSize = fs.Length - offset;
}
fs.Read(buff, 0, Convert.ToInt32(readSize)); // 读取一段数据到缓冲区
if (offset + readSize < fs.Length) // 不是最后一块
{
md5.TransformBlock(buff, 0, Convert.ToInt32(readSize), buff, 0);
}
else // 最后一块
{
md5.TransformFinalBlock(buff, 0, Convert.ToInt32(readSize));
}
offset += bufferSize;//在这里汇报进度即可
}
fs.Close();
byte[] result = md5.Hash;
md5.Clear();
StringBuilder sb = new StringBuilder(32);
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("X2"));
}
return sb.ToString();
}