以前写过这样一篇文章(ASP.NET文件下载函数(好用的东东)),发现很多朋友询问,并且有时候会发生错误,今天我再重新更新一下,利用IHttpHandler来实现多扩展名文件下载,思路是这样:
1. 首先新建一个用于进行下载处理的page页,如download.aspx,里面什么东西也没有。
2. 添加一个DownloadHandler类,它继承于IHttpHandler接口,可以用来自定义HTTP 处理程序同步处理HTTP的请求。
public
class
DownloadHandler : IHttpHandler
{
public
void
ProcessRequest(HttpContext context)
{
HttpResponse Response
=
context.Response;
HttpRequest Request
=
context.Request;
System.IO.Stream iStream
=
null
;
byte
[] buffer
=
new
Byte[
10240
];
int
length;
long
dataToRead;
try
{
string
filename
=
FileHelper.Decrypt(Request[
"
fn
"
]);
//
通过解密得到文件名
string
filepath
=
HttpContext.Current.Server.MapPath(
"
~/
"
)
+
"
files/
"
+
filename;
//
待下载的文件路径
iStream
=
new
System.IO.FileStream(filepath, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read);
Response.Clear();
dataToRead
=
iStream.Length;
long
p
=
0
;
if
(Request.Headers[
"
Range
"
]
!=
null
)
{
Response.StatusCode
=
206
;
p
=
long
.Parse(Request.Headers[
"
Range
"
].Replace(
"
bytes=
"
,
""
).Replace(
"
-
"
,
""
));
}
if
(p
!=
0
)
{
Response.AddHeader(
"
Content-Range
"
,
"
bytes
"
+
p.ToString()
+
"
-
"
+
((
long
)(dataToRead
-
1
)).ToString()
+
"
/
"
+
dataToRead.ToString());
}
Response.AddHeader(
"
Content-Length
"
, ((
long
)(dataToRead
-
p)).ToString());
Response.ContentType
=
"
application/octet-stream
"
;
Response.AddHeader(
"
Content-Disposition
"
,
"
attachment; filename=
"
+
System.Web.HttpUtility.UrlEncode(System.Text.Encoding.GetEncoding(
65001
).GetBytes(Path.GetFileName(filename))));
iStream.Position
=
p;
dataToRead
=
dataToRead
-
p;
while
(dataToRead
>
0
)
{
if
(Response.IsClientConnected)
{
length
=
iStream.Read(buffer,
0
,
10240
);
Response.OutputStream.Write(buffer,
0
, length);
Response.Flush();
buffer
=
new
Byte[
10240
];
dataToRead
=
dataToRead
-
length;
}
else
{
dataToRead
=
-
1
;
}
}
}
catch
(Exception ex)
{
Response.Write(
"
Error :
"
+
ex.Message);
}
finally
{
if
(iStream
!=
null
)
{
iStream.Close();
}
Response.End();
}
}
public
bool
IsReusable
{
get
{
return
true
; }
}
}
3. 这里涉及到一个文件名加解密的问题,是为了防止文件具体名称暴露在状态栏中,所以添加一个FileHelper类,代码如下:
public
class
FileHelper
{
public
static
string
Encrypt(
string
filename)
{
byte
[] buffer
=
HttpContext.Current.Request.ContentEncoding.GetBytes(filename);
return
HttpUtility.UrlEncode(Convert.ToBase64String(buffer));
}
public
static
string
Decrypt(
string
encryptfilename)
{
byte
[] buffer
=
Convert.FromBase64String(encryptfilename);
return
HttpContext.Current.Request.ContentEncoding.GetString(buffer);
}
}
利用Base64码对文件名进行加解密处理。
4. 在Web.config上,添加httpHandlers结点,如下:
<
system.web
>
<
httpHandlers
>
<
add
verb
="*"
path
="download.aspx"
type
="DownloadHandler"
/>
</
httpHandlers
>
</
system.web
>
5. 现在新建一个aspx页面,对文件进行下载:
Default.aspx代码如下:
Default.aspx Code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>文件下载</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:HyperLink ID="link" runat="server" Text="文件下载"></asp:HyperLink>
</div>
</form>
</body>
</html>
Default.aspx.cs代码如下:
Default.aspx.cs Code
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string url = FileHelper.Encrypt("DesignPattern.chm");
link.NavigateUrl = "~/download.aspx?fn=" + url;
}
}
这样就实现了文件下载时,不管是什么格式的文件,都能够弹出打开/保存窗口。:)
源码下载:DownloadSolution.rar