C# 创建自定义文件下载。MD5哈希不';不匹配
我使用Asp.NETMVC创建了一个文件下载程序。内置Asp.NETMVC函数的问题在于,它们无法处理超大文件下载,在某些浏览器中,它们无法弹出“另存为”对话框。所以我自己使用了msdn的一篇文章。现在的问题是,文件下载得很完美,但MD5校验和不匹配,因为服务器上的文件大小与下载的文件稍有不同(尽管1000次测试表明下载执行得很好)。代码如下:C# 创建自定义文件下载。MD5哈希不';不匹配,c#,asp.net-mvc,download,C#,Asp.net Mvc,Download,我使用Asp.NETMVC创建了一个文件下载程序。内置Asp.NETMVC函数的问题在于,它们无法处理超大文件下载,在某些浏览器中,它们无法弹出“另存为”对话框。所以我自己使用了msdn的一篇文章。现在的问题是,文件下载得很完美,但MD5校验和不匹配,因为服务器上的文件大小与下载的文件稍有不同(尽管1000次测试表明下载执行得很好)。代码如下: public class CustomFileResult : ActionResult { public string File { get;
public class CustomFileResult : ActionResult
{
public string File { get; set; }
public CustomFileResult(string file)
{
this.File = file;
}
public override void ExecuteResult(ControllerContext context)
{
Stream iStream = null;
// Buffer to read 10K bytes in chunk:
byte[] buffer = new Byte[10000];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
// Identify the file name.
string filename = System.IO.Path.GetFileName(this.File);
try
{
// Open the file.
iStream = new System.IO.FileStream(this.File, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read);
// Total bytes to read:
dataToRead = iStream.Length;
context.HttpContext.Response.ContentType = "application/octet-stream";
context.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (context.HttpContext.Response.IsClientConnected)
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 10000);
// Write the data to the current output stream.
context.HttpContext.Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
context.HttpContext.Response.Flush();
buffer = new Byte[10000];
dataToRead = dataToRead - length;
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
context.HttpContext.Response.Write("Error : " + ex.Message);
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
}
context.HttpContext.Response.Close();
}
}
}
以及执行:
return new CustomFileResult(file.FullName);
尝试使用
Response.TransmitFile(string fileName)
方法
这真的很好,并且有一些东西可以避免超出记忆的预期
您的问题在于:
length = iStream.Read(buffer, 0, 10000);
// Write the data to the current output stream.
context.HttpContext.Response.OutputStream.Write(buffer, 0, length);
每个循环读入一个正好10000字节的缓冲区,并将其写入流。这意味着有人下载的每个文件都是10000的倍数。因此,如果我从你的站点下载一个9998字节的文件,我得到的文件将是10000字节。这意味着散列永远不会匹配。我的文件末尾有2个空字节
您需要添加一个检查,以确保要读取的数据量>=10k,如果不是,请将字节大小调整为剩余的确切数量,然后传输该数据。这将修复散列不匹配的问题
试着这样做:
if (context.HttpContext.Response.IsClientConnected)
{
// Read the data in buffer.
if (dataToRead>=10000)
{
byte[] buffer = new byte[10000];
length = 10000
context.HttpContext.Response.OutputStream.Write(buffer, 0, length);
}
else
{
byte[] buffer = new byte[dataToRead];
length = buffer.Length;
context.HttpContext.Response.OutputStream.Write(buffer, 0, length);
}
// Flush the data to the HTML output.
context.HttpContext.Response.Flush();
dataToRead = dataToRead - length;
}
一旦开始写入OutputStream,请尝试刷新OutputStream本身,而不是刷新响应:
context.HttpContext.Response.OutputStream.Flush()
发现问题是缺少标题
context.HttpContext.Response.AddHeader("Content-Length", iStream.Length.ToString());
添加该头解决了问题。您不需要每次都重新初始化
缓冲区。另外,使用break
.iStream.Read将返回它读取的字节数。最后一次读取将少于10000。10000是要读取的最大字节数。他将实际字节数存储在长度变量中。@Dana,Scrum Meister-你们都完全正确。我误读到他在存储变量中读取的字节数。那会教我不要仔细阅读。