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. KVM和QEMU简介

    KVM/QEMU简介 KVM虚拟机是基于linux内核虚拟化,自linux2.6.20之后就集成在linux的各个主要发行版本中.它使用linux自身的调度器进行管理,所以相对于xen,其核心源码很少 ...

  2. 12174 - Shuffle

    这道题能够用"滑动窗体"的思想来做,假想一个滑动的窗体,这个窗体的大小是s.划过一个大小为n的区域,可是由于s可能比n大,所以我们最好还是不去考虑s和n的大小,直接开出一个足够大的 ...

  3. General PE format layout

  4. STM32输入捕获模式设置并用DMA接收数据

    参考: STM32的PWM输入模式设置并用DMA接收数据 Input capture mode The input stage samples the corresponding TIx input ...

  5. PHPWord 打印 快递单/合同

    打印快递单有个特点: 被打印纸的背景是固定的, 你只能 在合适的位置输入快递单的内容,操作步骤如下: 1.制作 word 模板 参考文章 “图解如何用打印机套打快递单” 2.在 模板 中放置“占位符” ...

  6. CRC校验的实现

    本例提供的是通过查表发来实现CRC校验. CRC余式表如下: unsigned int crctab[256] ={/*CRC余式表 */ 0x0000, 0x1021, 0x2042, 0x3063 ...

  7. Revit Family API 添加参数与尺寸标注

    使用FamilyManager其他的与普通添加参数与标注没区别. [TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Man ...

  8. DOM对象之document对象

    DOM对象:当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model). HTML DOM 模型被构造为对象的树. 打开网页后,首先看到的是浏览器窗口,即顶层的win ...

  9. Promise,Generator(生成器),async(异步)函数

    Promise 是什么 Promise是异步编程的一种解决方案.Promise对象表示了异步操作的最终状态(完成或失败)和返回的结果. 其实我们在jQuery的ajax中已经见识了部分Promise的 ...

  10. lastlog

    [root@li739-39 ~]# lastlogUsername Port From Latestroot pts/1 183.15.253.245 Thu Oct 29 05:57:29 +00 ...