使用Asp.Net MVC我正在创建一个文件下载器。内置的Asp.Net MVC功能的问题在于它们不能用于非常大的文件下载,在某些浏览器中它们不会弹出另存为对话框。所以我使用msdn http://support.microsoft.com/kb/812406中的一篇文章自己推出。现在的问题是文件下载完美,但MD5校验和不匹配,因为服务器上的文件大小与下载略有不同(即使1000个测试表明下载执行得很好)。这是代码:
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);
答案 0 :(得分:2)
尝试使用
Response.TransmitFile(string fileName)
方法
这是非常好的,也有一些东西可以避免OutOfMemory考试。
http://msdn.microsoft.com/en-us/library/12s31dhy(v=vs.80).aspx
答案 1 :(得分:1)
原来问题是缺少标题。
context.HttpContext.Response.AddHeader("Content-Length", iStream.Length.ToString());
添加该标题解决了这个问题。
答案 2 :(得分:0)
一旦开始写入OutputStream,请尝试刷新OutputStream本身而不是刷新响应:
context.HttpContext.Response.OutputStream.Flush()
答案 3 :(得分:-1)
你的问题在这里:
length = iStream.Read(buffer, 0, 10000);
// Write the data to the current output stream.
context.HttpContext.Response.OutputStream.Write(buffer, 0, length);
每个循环读入一个精确10,000字节的缓冲区并将其写入流。这意味着某人下载的每个文件都将是10,000的倍数。因此,如果我要从您的站点下载9,998字节的文件,我得到的文件将是10,000字节。意味着哈希永远不会匹配。我的文件末尾有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;
}