Downloading files from a server to client, using ASP.Net, when file size is too big for MemoryStream using Generic Handlers (ashx)
Currently, I was trying to write an ASP.Net application that involved a user clicking a ASP.Net button control
C#
|
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.
C#
{
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
C#
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
C#
|
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
C#
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)的更多相关文章
- [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 ...
- [转] Spring MVC sample application for downloading files
http://www.codejava.net/frameworks/spring/spring-mvc-sample-application-for-downloading-files n this ...
- TCP连接的状态与关闭方式及其对Server与Client的影响
TCP连接的状态与关闭方式及其对Server与Client的影响 1. TCP连接的状态 首先介绍一下TCP连接建立与关闭过程中的状态.TCP连接过程是状态的转换,促使状态发生转换的因素包括用户调用. ...
- navicat 连接sqlserver提示要安装 sql server native client
navicat 连接sqlserver提示要安装 sql server native client 解决方法:其实navicat自带sqlncli_x64.msi,就在安装目录下,安装后问题解决!
- 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 ...
- 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 ...
- Netty4.0学习笔记系列之一:Server与Client的通讯
http://blog.csdn.net/u013252773/article/details/21046697 本文是学习Netty的第一篇文章,主要对Netty的Server和Client间的通讯 ...
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service ...
- 基于winsocket的框体Server和Client
前面学了一点Winsock的知识,会编写简单的Server和Client,现在就想通过VS2008编写框体的Server和Client,而不是在控制台上的操作了,毕竟学编程就是要多加练习,在实践中发现 ...
随机推荐
- Xamarin iOS教程之使用按钮接接收用户输入
Xamarin iOS教程之使用按钮接接收用户输入 Xamarin iOS使用按钮接接收用户输入 按钮是用户交互的最基础控件.即使是在iPhone或者iPad中,用户使用最多操作也是通过触摸实现点击. ...
- python基础之return,参数
函数的返回值 1.什么是返回值: 返回值是一个函数的处理结果 2.为什么要有返回值 如果需要在程序中拿到函数的处理结果,做进一步的处理,则需要函数必须有返回值 3.函数返回值的应用: 函数的返回值用r ...
- lvs+keepalived 02
LVS keepalived 高可用负载均衡 环境 IP HOSTNAME Describe 192.168.100.30 lvs01 主负载 192.168.100.31 lvs02 备负载 192 ...
- Xtreme9.0 - Block Art 线段树
Block Art 题目连接: https://www.hackerrank.com/contests/ieeextreme-challenges/challenges/block-art Descr ...
- Codeforces Round #375 (Div. 2) E. One-Way Reform 欧拉路径
E. One-Way Reform 题目连接: http://codeforces.com/contest/723/problem/E Description There are n cities a ...
- Linux __attribute__(("hidden"))、default
记录下: Linux下导出so库接口时在下面情况下无法导出(编译时增加了__attribute__(("hidden"))属性). void * __attribute__((&q ...
- html5 js实现浏览器全屏
全屏 var docElm = document.documentElement; //W3C if (docElm.requestFullscreen) { docElm.requestFullsc ...
- java 虚拟机启动参数 (转)
在Java.J2EE大型应用中,JVM非标准参数的配置直接关系到整个系统的性能. JVM非标准参数指的是JVM底层的一些配置参数,这些参数在一般开发中默认即可,不需要任何配置.但是在生产环境中,为了提 ...
- 调试工具BTrace 的使用--例子
http://www.cnblogs.com/serendipity/archive/2012/05/14/2499840.html
- [Winform]无边框窗口悬浮右下角并可以拖拽移动
摘要 简单实现了一个这样的功能,程序启动时,窗口悬固定在右下角,并可以通过鼠标拖拽移动. 核心代码块 无边框窗口并不出现在任务栏 //无边框 this.FormBorderStyle = System ...