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. ApiPost自动化测试基础之:接口参数依赖的情景处理

    在<ApiPost环境变量之第1课>里,我们介绍了什么是ApiPost环境变量,并如何定义.使用它. 环境变量.接口参数依赖的处理是ApiPost自动化测试的基础.本文主要讲解接口参数依赖 ...

  2. Node.js用6行代码1个JS文件搭建一个HTTP静态服务器

    Node.js是一个基于Chrome的JavaScript运行时的用户以轻松构建快速.可扩展的网络应用平台. Node.js使用事件驱动.非阻塞I/ O模型,使它轻量级.高效和完美的适用于运行在分布式 ...

  3. 【BZOJ-4031】小z的房间 Matrix-Tree定理 + 高斯消元解行列式

    4031: [HEOI2015]小Z的房间 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 937  Solved: 456[Submit][Statu ...

  4. Codeforces Round #272 (Div. 2) B. Dreamoon and WiFi dp

    B. Dreamoon and WiFi 题目连接: http://www.codeforces.com/contest/476/problem/B Description Dreamoon is s ...

  5. hdu 5784 How Many Triangles 计算几何,平面有多少个锐角三角形

    How Many Triangles 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5784 Description Alice has n poin ...

  6. ASP.NET Core 中的框架级依赖注入

    https://tech.io/playgrounds/5040/framework-level-dependency-injection-with-asp-net-core 作者: Gunnar P ...

  7. Git 忽略某个目录中的文件,同时保留这个目录

    类似的一个问题是项目根目录下可能有 logs 一类的目录, 我们希望他人把仓库 clone 下来的时候能够已经携带了这个目录, 但又不希望让这个目录中的日志文件进版本库. 之前看到一些项目用了一种比较 ...

  8. 添加Godaddy二级域名子域名方法

    我们在申请注册了Godaddy域名后,如果需要开通二级域名,方法简单只需要在Godaddy添加二级域名(子域名)只要在域名管理后台添加A记录或CNAME别名(Aliases)即可.但我们如果需要添加二 ...

  9. 该对象尚未初始化。请确保在所有其他初始化代码后面的应用程序启动代码中调用 HttpConfiguration.EnsureInitialized()。

    WebAPI使用属性路由,配置config.MapHttpAttributeRoutes();后出现错误: System.InvalidOperationException: 该对象尚未初始化.请确保 ...

  10. Windows Phone本地数据库(SQLCE):6、[Index] attribute(翻译)(转)

    这是“windows phone mango本地数据库(sqlce)”系列短片文章的第六篇. 为了让你开始在Windows Phone Mango中使用数据库,这一系列短片文章将覆盖所有你需要知道的知 ...