Currently, I was trying to write an ASP.Net application that involved a user clicking a ASP.Net button control

 
 
 
 
 
 

C#

 
<asp:Button ID="btnDownload" runat="server" Text="Download File" OnClick="btnDownload_Click"/>
1
2
3
 
<asp:Button ID="btnDownload"runat="server"Text="Download File"OnClick="btnDownload_Click"/>
 

Once the control is clicked the back end stores the users information (first name, last name, email address, phone number, etc…) to a database. After that information is stored to a database, the system would then allow the user to download the file through an generic handler (.ashx file). The file size that was to be downloaded is 600MB.

Download button onclick event handler

 
 
 
 
 
 

C#

 
protected void btnDownload_Click(object sender, EventArgs e)
{
connectionString = WebConfigurationManager.ConnectionStrings["connectionstring"].ConnectionString;
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("UserDownloadedFile", con);
cmd.CommandType = CommandType.StoredProcedure;

cmd.Parameters.Add(new SqlParameter("@Guid", SqlDbType.UniqueIdentifier));
cmd.Parameters["@Guid"].Value = new Guid(ViewState["Guid"].ToString());

try
{
int rowsAffected;
rowsAffected = 0;
con.Open();

rowsAffected = cmd.ExecuteNonQuery();

if (rowsAffected > 0)
{
Response.Redirect("http://localhost/someWebApp/DownloadFile.ashx");
}
else
{
// Something went wrong.
}
}
catch (SqlException exception)
{
// Log exception
}
finally
{
con.Close();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
protectedvoidbtnDownload_Click(objectsender,EventArgse)
    {
        connectionString=WebConfigurationManager.ConnectionStrings["connectionstring"].ConnectionString;
        SqlConnection con=newSqlConnection(connectionString);
        SqlCommand cmd=newSqlCommand("UserDownloadedFile",con);
        cmd.CommandType=CommandType.StoredProcedure;
 
        cmd.Parameters.Add(newSqlParameter("@Guid",SqlDbType.UniqueIdentifier));
        cmd.Parameters["@Guid"].Value=newGuid(ViewState["Guid"].ToString());
 
        try
        {
            introwsAffected;
            rowsAffected=0;
            con.Open();
 
            rowsAffected=cmd.ExecuteNonQuery();
 
            if(rowsAffected>0)
            {
                 Response.Redirect("http://localhost/someWebApp/DownloadFile.ashx");
            }
            else
            {
                  // Something went wrong.
            }
        }
        catch(SqlException exception)
        {
               // Log exception
        }
        finally
        {
            con.Close();
        }
    }
 

Once the database is updated, I call the DownloadFile.ashx generic handler. Upon execution of the generic handler I received the following “OutOfMemoryException” error

This was a result from the following generic handler I was using

Former DownloadFile generic handler

 
 
 
 
 
 

C#

 
<%@ WebHandler Language="C#" class="DownloadFile" %>

using System;
using System.IO;
using System.Web;

public class DownloadFile : IHttpHandler {

public void ProcessRequest(HttpContext context)
{
string mediaName = "myFile.zip"; // 600MB in file size

if (string.IsNullOrEmpty(mediaName))
{
return;
}

string destPath = context.Server.MapPath("~/Downloads/" + mediaName);
// Check to see if file exist
FileInfo fi = new FileInfo(destPath);

// If the file exist on the server then add it to the database
if (fi.Exists)
{
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AppendHeader("Content-Length", fi.Length.ToString());
HttpContext.Current.Response.ContentType = "application/x-zip-compressed";
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" + mediaName);
HttpContext.Current.Response.BinaryWrite(ReadByteArryFromFile(destPath));
HttpContext.Current.Response.End();
}
}

private byte[] ReadByteArryFromFile(string destPath)
{
byte[] buff = null;
FileStream fs = new FileStream(destPath, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long numBytes = new FileInfo(destPath).Length;
buff = br.ReadBytes((int)numBytes);
return buff;
}

public bool IsReusable
{
get
{
return false;
}
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 
<%@WebHandlerLanguage="C#"Class="DownloadFile"%>
 
usingSystem;
usingSystem.IO;
usingSystem.Web;
 
publicclassDownloadFile:IHttpHandler{
 
    publicvoidProcessRequest(HttpContext context)
    {
        stringmediaName="myFile.zip";// 600MB in file size
 
        if(string.IsNullOrEmpty(mediaName))
        {
            return;
        }
 
        stringdestPath=context.Server.MapPath("~/Downloads/"+mediaName);
        // Check to see if file exist
        FileInfo fi=newFileInfo(destPath);
 
        // If the file exist on the server then add it to the database
        if(fi.Exists)
        {
            HttpContext.Current.Response.ClearHeaders();
            HttpContext.Current.Response.ClearContent();
            HttpContext.Current.Response.AppendHeader("Content-Length",fi.Length.ToString());
            HttpContext.Current.Response.ContentType="application/x-zip-compressed";
            HttpContext.Current.Response.AppendHeader("Content-Disposition","attachment; filename="+mediaName);
            HttpContext.Current.Response.BinaryWrite(ReadByteArryFromFile(destPath));
            HttpContext.Current.Response.End();
        }
    }
 
    privatebyte[]ReadByteArryFromFile(stringdestPath)
    {
        byte[]buff=null;
        FileStream fs=newFileStream(destPath,FileMode.Open,FileAccess.Read);
        BinaryReader br=newBinaryReader(fs);
        longnumBytes=newFileInfo(destPath).Length;
        buff=br.ReadBytes((int)numBytes);
        returnbuff;
    }
 
    publicboolIsReusable
    {
        get
        {
            returnfalse;
        }
    }
 
}
 

This handler worked in the past, for very small files. The last time I was using this the file size was about 300MB. My friend @homeraguas reminded me that I might needed to check my web.config file to be sure that the following maxRequestLength and executionTimeout was set. It wasn’t in the web.config file. So I added the following

httpRuntime maxRequestLength and executionTimeout settings

 
 
 
 
 
 

C#

 
<httpRuntime maxRequestLength="600000" executionTimeout="7200"/>
1
2
3
 
<httpRuntime maxRequestLength="600000"executionTimeout="7200"/>
 

Recompiled and published, then gave it another go. Still, I came across the “OutOfMemoryException” error. I looked around the net and came across this blog’s article utilizing the following method Reponse.TransmitFile();

The HttpReponse.TransmitFile()method basically states it “Writes the specified file directly to an HTTP response output stream without buffering it in memory.”

This makes sense to me, since the file I want to transfer is 600MB and I do not think the current server I am writing this web application for does not have adequate resources available. So the revision to the code I wrote/used is as follows

Current DownloadFile.ashx generic handler

 
 
 
 
 
 

C#

 
<%@ WebHandler Language="C#" class="DownloadFile" %>

using System;
using System.IO;
using System.Web;

public class DownloadFile : IHttpHandler {

public void ProcessRequest(HttpContext context)
{
string mediaName = "myFile.zip"; // 600MB in file size
if (string.IsNullOrEmpty(mediaName))
{
return;
}

string destPath = context.Server.MapPath("~/Downloads/" + mediaName);
// Check to see if file exist
FileInfo fi = new FileInfo(destPath);

try
{
if (fi.Exists)
{
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" + fi.Name);
HttpContext.Current.Response.AppendHeader("Content-Length", fi.Length.ToString());
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.TransmitFile(fi.FullName);
HttpContext.Current.Response.Flush();
}
}
catch (Exception exception)
{
HttpContext.Current.Response.ContentType = "text/plain";
HttpContext.Current.Response.Write(exception.Message);
}
finally
{
HttpContext.Current.Response.End();
}
}

public bool IsReusable
{
get
{
return false;
}
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 
<%@WebHandlerLanguage="C#"Class="DownloadFile"%>
 
usingSystem;
usingSystem.IO;
usingSystem.Web;
 
publicclassDownloadFile:IHttpHandler{
 
    publicvoidProcessRequest(HttpContext context)
    {        
        stringmediaName="myFile.zip";// 600MB in file size
        if(string.IsNullOrEmpty(mediaName))
        {
            return;
        }
 
        stringdestPath=context.Server.MapPath("~/Downloads/"+mediaName);
        // Check to see if file exist
        FileInfo fi=newFileInfo(destPath);
 
        try
        {
            if(fi.Exists)
            {
                HttpContext.Current.Response.ClearHeaders();
                HttpContext.Current.Response.ClearContent();
                HttpContext.Current.Response.AppendHeader("Content-Disposition","attachment; filename="+fi.Name);
                HttpContext.Current.Response.AppendHeader("Content-Length",fi.Length.ToString());
                HttpContext.Current.Response.ContentType="application/octet-stream";
                HttpContext.Current.Response.TransmitFile(fi.FullName);
                HttpContext.Current.Response.Flush();                
            }
        }
        catch(Exception exception)
        {
            HttpContext.Current.Response.ContentType="text/plain";
            HttpContext.Current.Response.Write(exception.Message);
        }
        finally
        {
            HttpContext.Current.Response.End();
        }
    }
 
    publicboolIsReusable
    {
        get
        {
            returnfalse;
        }
    }
 
}
 

The result was that it worked.

What do you guys think? Is this an adequate solution? Have a good one!

Downloading files from a server to client, using ASP.Net, when file size is too big for MemoryStream using Generic Handlers (ashx)的更多相关文章

  1. [DeploymentService:290066]Error occurred while downloading files from admin server for deployment request "0". Underlying error is: "null"

    weblogic 莫名无法启动: <Apr , :: PM CST> <Error> <Deployer> <BEA-> <Failed to i ...

  2. [转] Spring MVC sample application for downloading files

    http://www.codejava.net/frameworks/spring/spring-mvc-sample-application-for-downloading-files n this ...

  3. TCP连接的状态与关闭方式及其对Server与Client的影响

    TCP连接的状态与关闭方式及其对Server与Client的影响 1. TCP连接的状态 首先介绍一下TCP连接建立与关闭过程中的状态.TCP连接过程是状态的转换,促使状态发生转换的因素包括用户调用. ...

  4. navicat 连接sqlserver提示要安装 sql server native client

    navicat 连接sqlserver提示要安装 sql server native client 解决方法:其实navicat自带sqlncli_x64.msi,就在安装目录下,安装后问题解决!

  5. C Socket Programming for Linux with a Server and Client Example Code

    Typically two processes communicate with each other on a single system through one of the following ...

  6. sql System.Data.SqlClient.SqlError: 无法覆盖文件 'C:\Program Files\Microsoft SQL Server\MSSQL\data\itsm_Data.MDF'。数据库 'my1' 正在使用该文件的解决方案

    对数据库备份进行还原时遇到“sql System.Data.SqlClient.SqlError: 无法覆盖文件 'C:\Program Files\Microsoft SQL Server\MSSQ ...

  7. Netty4.0学习笔记系列之一:Server与Client的通讯

    http://blog.csdn.net/u013252773/article/details/21046697 本文是学习Netty的第一篇文章,主要对Netty的Server和Client间的通讯 ...

  8. 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service ...

  9. 基于winsocket的框体Server和Client

    前面学了一点Winsock的知识,会编写简单的Server和Client,现在就想通过VS2008编写框体的Server和Client,而不是在控制台上的操作了,毕竟学编程就是要多加练习,在实践中发现 ...

随机推荐

  1. java中远程http文件上传及file2multipartfile

    工作中有时会遇到各种需求,你得变着法儿去解决,当然重要的是在什么场景中去完成. 比如Strut2中file类型如何转换成multipartfile类型,找了几天,发现一个变通的方法记录如下(虽然最后没 ...

  2. js原型鏈與js繼承解析

    最近在網上看了諸多js原型鏈的解析,說得雲裡霧裡,不明所以.徹底了解後,決定出個博客記錄一下,一是方便後來人學習,二是方便日後複習. 首先,我們來看一下構造函數.原型.實例之間的關係圖: 所以,我們通 ...

  3. luoguP4000 斐波那契数列

    题目链接 luoguP4000 斐波那契数列 题解 根据这个东西 https://www.cnblogs.com/sssy/p/9418732.html 我们可以找出%p意义下的循环节 然后就可以做了 ...

  4. Bzoj2534:后缀自动机 主席树启发式合并

    国际惯例的题面:考虑我们求解出字符串uvu第一个u的右端点为i,第二个u的右端点为j,我们需要满足什么性质?显然j>i+L,因为我们选择的串不能是空串.另外考虑i和j的最长公共前缀(也就是说其p ...

  5. (android高仿系列)今日头条 --新闻阅读器 (转载)

    非常不错,原文地址:http://blog.csdn.net/vipzjyno1/article/details/26514543

  6. [CQOI2007]涂色

    [CQOI2007]涂色 题目大意: 假设你有一条长度为\(n\)的木版,初始时没有涂过任何颜色.每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色.问达到给定的目标至少要多少次操 ...

  7. 华为S5300系列交换机限制特定IP可以登录Web

    针对Web管理可能有如下需求: 1.限制某个特定IP允许访问Web 2.默认修改80端口访问 那么针对上面的设置可以有效杜绝而已Web密码暴力破解,增强交换机安全等. 实现: 1.限制特定IP登录We ...

  8. PG的集群技术:Pgpool-II与Postgres-XC Postgres-XL Postgres-XZ Postges-x2

    https://segmentfault.com/a/1190000007012082 https://www.postgres-xl.org/ https://www.biaodianfu.com/ ...

  9. webpack原理与实战

    webpack是一个js打包工具,不一个完整的前端构建工具.它的流行得益于模块化和单页应用的流行.webpack提供扩展机制,在庞大的社区支持下各种场景基本它都可找到解决方案.本文的目的是教会你用we ...

  10. 内存映射函数remap_pfn_range学习——示例分析(1)

    span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }.CodeMirror ...