Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 创建自定义文件下载。MD5哈希不';不匹配_C#_Asp.net Mvc_Download - Fatal编程技术网

C# 创建自定义文件下载。MD5哈希不';不匹配

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;

我使用Asp.NETMVC创建了一个文件下载程序。内置Asp.NETMVC函数的问题在于,它们无法处理超大文件下载,在某些浏览器中,它们无法弹出“另存为”对话框。所以我自己使用了msdn的一篇文章。现在的问题是,文件下载得很完美,但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);
尝试使用

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-你们都完全正确。我误读到他在存储变量中读取的字节数。那会教我不要仔细阅读。