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,而不是在控制台上的操作了,毕竟学编程就是要多加练习,在实践中发现 ...
随机推荐
- BZOJ.2111.[ZJOI2010]排列计数(DP Lucas)
题目链接 对于\(a_i>a_{i/2}\),我们能想到小根堆.题意就是,求构成大小为\(n\)的小根堆有多少种方案. 考虑DP,\(f[i]\)表示构成大小为\(i\)的小根堆的方案数,那么如 ...
- 8、Redis中sort命令详解
写在前面的话:读书破万卷,编码如有神 ------------------------------------------------- 1.排序 (1)sort:可以对List.Set.ZSet里面 ...
- Codeforces Beta Round #14 (Div. 2) A. Letter 水题
A. Letter 题目连接: http://www.codeforces.com/contest/14/problem/A Description A boy Bob likes to draw. ...
- 马士兵hadoop第五课:java开发Map/Reduce
马士兵hadoop第一课:虚拟机搭建和安装hadoop及启动 马士兵hadoop第二课:hdfs集群集中管理和hadoop文件操作 马士兵hadoop第三课:java开发hdfs 马士兵hadoop第 ...
- RubyMine8 安装
在win7下面安装RubyMine8 中文 汉化 1.需要下载 RubyMine8的程序包 2.先安装好 RubyMine8 很简单 点击下一步就可以 选择安装目录这应该就不需要说了 3.汉化 ...
- Slickflow.NET 开源工作流引擎基础介绍(十) -- 邮件轮询异步发送模块集成
前言:在任务数据生成时,为了让办理任务的用户及时获取到待办任务的主题和内容,需要发送通知类的消息,而电子邮件和手机端的短信通知则是比较普通的消息发送.本文是针对电子邮件异步发送模块的实现来做实例说明. ...
- Graph database_neo4j 底层存储结构分析(2)
3 neo4j存储结构 neo4j 中,主要有4类节点,属性,关系等文件是以数组作为核心存储结构:同时对节点,属性,关系等类型的每个数据项都会分配一个唯一的ID,在存储时以该ID 为数组的 ...
- 群晖NAS百度云Docker客户端下载目录没有权限的问题解决
针对这篇文章:https://zhuanlan.zhihu.com/p/42267779的问题,需要ssh进去群晖,然后把目录设置成777权限.命令如下: sudo chmod -R 777 /vol ...
- STM32 Timer : Auto-reload register register
Auto-reload register (TIMx_ARR) The auto-reload register is preloaded. Writing to or reading from th ...
- CTreeCtrl和CListCtrl失去焦点时高亮选中项
设置CTreeCtrl的Always Show Selection:TrueCListCtrl的Always Show Selection:False在NM_CUSTOMDRAW事件中添加如下代码: ...