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,而不是在控制台上的操作了,毕竟学编程就是要多加练习,在实践中发现 ...
随机推荐
- java中远程http文件上传及file2multipartfile
工作中有时会遇到各种需求,你得变着法儿去解决,当然重要的是在什么场景中去完成. 比如Strut2中file类型如何转换成multipartfile类型,找了几天,发现一个变通的方法记录如下(虽然最后没 ...
- js原型鏈與js繼承解析
最近在網上看了諸多js原型鏈的解析,說得雲裡霧裡,不明所以.徹底了解後,決定出個博客記錄一下,一是方便後來人學習,二是方便日後複習. 首先,我們來看一下構造函數.原型.實例之間的關係圖: 所以,我們通 ...
- luoguP4000 斐波那契数列
题目链接 luoguP4000 斐波那契数列 题解 根据这个东西 https://www.cnblogs.com/sssy/p/9418732.html 我们可以找出%p意义下的循环节 然后就可以做了 ...
- Bzoj2534:后缀自动机 主席树启发式合并
国际惯例的题面:考虑我们求解出字符串uvu第一个u的右端点为i,第二个u的右端点为j,我们需要满足什么性质?显然j>i+L,因为我们选择的串不能是空串.另外考虑i和j的最长公共前缀(也就是说其p ...
- (android高仿系列)今日头条 --新闻阅读器 (转载)
非常不错,原文地址:http://blog.csdn.net/vipzjyno1/article/details/26514543
- [CQOI2007]涂色
[CQOI2007]涂色 题目大意: 假设你有一条长度为\(n\)的木版,初始时没有涂过任何颜色.每次你可以把一段连续的木版涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色.问达到给定的目标至少要多少次操 ...
- 华为S5300系列交换机限制特定IP可以登录Web
针对Web管理可能有如下需求: 1.限制某个特定IP允许访问Web 2.默认修改80端口访问 那么针对上面的设置可以有效杜绝而已Web密码暴力破解,增强交换机安全等. 实现: 1.限制特定IP登录We ...
- 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/ ...
- webpack原理与实战
webpack是一个js打包工具,不一个完整的前端构建工具.它的流行得益于模块化和单页应用的流行.webpack提供扩展机制,在庞大的社区支持下各种场景基本它都可找到解决方案.本文的目的是教会你用we ...
- 内存映射函数remap_pfn_range学习——示例分析(1)
span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }.CodeMirror ...