Response.BinaryWrite向客户端发送大文件
作者:admin 日期:2009-06-30
有时候我们需要向客户端发送文件,可以增加HTTP头Content-Disposition", "attachment; filename=fname.ext",然后用Response.BinaryWrite来向客户端写入二进制流,但这时候有个问题,IIS允许的写入最大应该是2M左右,当然具体多大我没有测过,但20M以上的绝对不可能写入,这个问题我摸索了几个小时,最后想到了C/S模式的客户端对服务器端的模式,然后测试,成功了。
以下是具体的代码:
先是ASP JScript版
引用内容
<%
function sendFileToClient(filepath)
{
filepath = filepath.replace(/^\s+|\s+$/g, "");
Response.Buffer = true; //打开buffer后,不知道效率会不会更高,你可以注释掉测试一下,注意下面的Clear(); Flush();也要一同注释掉。
Response.Clear();
var s = Server.CreateObject("ADODB.Stream");
s.Type = 1; //以binary打开
s.Open();
var filetype, filesize, filename, ContentType;
var fso;
var fileLen;
var file;
try
{
fso = Server.CreateObject("Scripting.FileSystemObject"); //创建FSO取得文件名,文件大小(其实不需要,直接用ADO就有size属性了。
file = fso.GetFile(filepath);
filename = file.name;
filesize = file.size;
filetype = filename.substring(filename.lastIndexOf(".")) || "";
switch(filetype.toLowerCase()) //根据文件后缀取得默认的MIME头
{
case ".asf":
ContentType = "video/x-ms-asf";
break;
case ".avi":
ContentType = "video/avi";
break;
case ".doc":
ContentType = "application/msword";
break;
case ".zip":
ContentType = "application/zip";
break;
case ".xls":
ContentType = "application/vnd.ms-excel";
break;
case ".gif":
ContentType = "image/gif";
break;
case ".jpg":
case ".jpeg":
ContentType = "image/jpeg";
break;
case ".wav":
ContentType = "audio/wav";
break;
case ".mp3":
ContentType = "audio/mpeg3";
break;
case ".mpg":
case ".mpeg":
ContentType = "video/mpeg";
break;
case ".rtf":
ContentType = "application/rtf";
break;
case ".htm":
case ".html":
ContentType = "text/html";
break;
case ".txt":
ContentType = "text/plain";
break;
default:
ContentType = "application/octet-stream";
}
s.LoadFromFile(filepath); //将文件加载入ADO
}
catch(e)
{
Response.Write(e.description);
Response.End();
}
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename); //增加“附加”文件的头信息,并指明文件名
Response.AddHeader("Content-Length", filesize); //增加文件大小
Response.CharSet = "UTF-8"; //这个要不要无所谓
Response.ContentType = ContentType; //增加MIME头
var bufferSize = 1048576; //指定每次向客户端写入多大的流,这里是1M
var cursor = 0;
s.Position = cursor; //ADO流的当前位置
while(true)
{
if((cursor + bufferSize) < filesize) //如果当前还没有读完
{
Response.BinaryWrite(s.Read(bufferSize)); //那么向客户端写入指定大小的数据
cursor += bufferSize;
s.Position = cursor; //ADO流位置向前增加
}
else //否则当前不够读取指定BUFFER的大小
{
Response.BinaryWrite(s.Read(filesize - cursor)); //读取剩下的数据
cursor += filesize - cursor;
break; //数据已读完,退出循环
}
Response.Flush(); //这个如果上面注释了Response.Buffer = true; 那么要把这个也注释掉,不知道哪个的效率更高些。
}
Response.Clear();
file = null; //注销对象
fso = null;
s.Close();
s = null;
}
%>
再是ASP VBScript版,下面的大部分注释都省略了,和上面的是一样的,不同的地方才写了注释
引用内容
<%
Sub sendFileToClient(ByVal filepath)
filepath = Trim(filepath)
'Response.Buffer = true '注释掉了
Response.Buffer = false
'Response.Clear
Dim s
Set s = Server.CreateObject("ADODB.Stream")
s.Type = 1
s.Open
Dim filetype, filesize, filename, ContentType
Dim fso
Dim fileLen
Dim file
On Error Resume Next
Set fso = Server.CreateObject("Scripting.FileSystemObject")
Set file = fso.GetFile(filepath)
filename = file.name
filesize = file.size
filetype = Mid(filename, InStrRev(filename, "."), Len(filename))
if IsEmpty(filetype) or IsNull(filetype) Then filetype = ""
Select Case LCase(filetype)
case ".asf"
ContentType = "video/x-ms-asf"
case ".avi"
ContentType = "video/avi"
case ".doc"
ContentType = "application/msword"
case ".zip"
ContentType = "application/zip"
case ".xls"
ContentType = "application/vnd.ms-excel"
case ".gif"
ContentType = "image/gif"
case ".jpg"
case ".jpeg"
ContentType = "image/jpeg"
case ".wav"
ContentType = "audio/wav"
case ".mp3"
ContentType = "audio/mpeg3"
case ".mpg"
case ".mpeg"
ContentType = "video/mpeg"
case ".rtf"
ContentType = "application/rtf"
case ".htm"
case ".html"
ContentType = "text/html"
case ".txt"
ContentType = "text/plain"
case else
ContentType = "application/octet-stream"
End Select
s.LoadFromFile(filepath)
If Err <> 0 Then
Response.Write Err.description
Err.Clear
Response.End
End If
Response.CharSet = "UTF-8"
Response.AddHeader "Content-Disposition", "attachment; filename=""" & filename & """;"
Response.AddHeader "Content-Length", filesize
Response.ContentType = ContentType
'只有这里有点不同,其实上面的JS版里面也可以直接用:
'for(var i = 0; i < Math.ceil(filesize / bufferSize); i++)
'{
' Response.BinaryWrite(s.Read(bufferSize));
'}
'也是一样的,只不过按JScript版本那样写是一种好习惯(规范一些),因为ASP里面的ADO有兼容,如果游标超出FILE_POS会自动读取至结尾,ADO的游标也会自动前进,但其它有些语言就不会这样了,会出错,在这里就直接偷懒吧
Dim i, bufferSize : bufferSize = 1048576
s.Position = 0
'直接偷懒
For i = 0 To filesize \ bufferSize
Response.BinaryWrite(s.Read(bufferSize))
Next
'Response.Clear();
Set file = Nothing
Set fso = Nothing
s.Close
Set s = Nothing
End Sub
%>
欢迎转载,但转载请注意保留原博客及作者信息
作者:JC
MSN:rot-apple@hotmail.com
Skype:ctv_jcyuan
博客:http://www.jc-space.com/blog
以下是具体的代码:
先是ASP JScript版
引用内容<%
function sendFileToClient(filepath)
{
filepath = filepath.replace(/^\s+|\s+$/g, "");
Response.Buffer = true; //打开buffer后,不知道效率会不会更高,你可以注释掉测试一下,注意下面的Clear(); Flush();也要一同注释掉。
Response.Clear();
var s = Server.CreateObject("ADODB.Stream");
s.Type = 1; //以binary打开
s.Open();
var filetype, filesize, filename, ContentType;
var fso;
var fileLen;
var file;
try
{
fso = Server.CreateObject("Scripting.FileSystemObject"); //创建FSO取得文件名,文件大小(其实不需要,直接用ADO就有size属性了。
file = fso.GetFile(filepath);
filename = file.name;
filesize = file.size;
filetype = filename.substring(filename.lastIndexOf(".")) || "";
switch(filetype.toLowerCase()) //根据文件后缀取得默认的MIME头
{
case ".asf":
ContentType = "video/x-ms-asf";
break;
case ".avi":
ContentType = "video/avi";
break;
case ".doc":
ContentType = "application/msword";
break;
case ".zip":
ContentType = "application/zip";
break;
case ".xls":
ContentType = "application/vnd.ms-excel";
break;
case ".gif":
ContentType = "image/gif";
break;
case ".jpg":
case ".jpeg":
ContentType = "image/jpeg";
break;
case ".wav":
ContentType = "audio/wav";
break;
case ".mp3":
ContentType = "audio/mpeg3";
break;
case ".mpg":
case ".mpeg":
ContentType = "video/mpeg";
break;
case ".rtf":
ContentType = "application/rtf";
break;
case ".htm":
case ".html":
ContentType = "text/html";
break;
case ".txt":
ContentType = "text/plain";
break;
default:
ContentType = "application/octet-stream";
}
s.LoadFromFile(filepath); //将文件加载入ADO
}
catch(e)
{
Response.Write(e.description);
Response.End();
}
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename); //增加“附加”文件的头信息,并指明文件名
Response.AddHeader("Content-Length", filesize); //增加文件大小
Response.CharSet = "UTF-8"; //这个要不要无所谓
Response.ContentType = ContentType; //增加MIME头
var bufferSize = 1048576; //指定每次向客户端写入多大的流,这里是1M
var cursor = 0;
s.Position = cursor; //ADO流的当前位置
while(true)
{
if((cursor + bufferSize) < filesize) //如果当前还没有读完
{
Response.BinaryWrite(s.Read(bufferSize)); //那么向客户端写入指定大小的数据
cursor += bufferSize;
s.Position = cursor; //ADO流位置向前增加
}
else //否则当前不够读取指定BUFFER的大小
{
Response.BinaryWrite(s.Read(filesize - cursor)); //读取剩下的数据
cursor += filesize - cursor;
break; //数据已读完,退出循环
}
Response.Flush(); //这个如果上面注释了Response.Buffer = true; 那么要把这个也注释掉,不知道哪个的效率更高些。
}
Response.Clear();
file = null; //注销对象
fso = null;
s.Close();
s = null;
}
%>
再是ASP VBScript版,下面的大部分注释都省略了,和上面的是一样的,不同的地方才写了注释
引用内容<%
Sub sendFileToClient(ByVal filepath)
filepath = Trim(filepath)
'Response.Buffer = true '注释掉了
Response.Buffer = false
'Response.Clear
Dim s
Set s = Server.CreateObject("ADODB.Stream")
s.Type = 1
s.Open
Dim filetype, filesize, filename, ContentType
Dim fso
Dim fileLen
Dim file
On Error Resume Next
Set fso = Server.CreateObject("Scripting.FileSystemObject")
Set file = fso.GetFile(filepath)
filename = file.name
filesize = file.size
filetype = Mid(filename, InStrRev(filename, "."), Len(filename))
if IsEmpty(filetype) or IsNull(filetype) Then filetype = ""
Select Case LCase(filetype)
case ".asf"
ContentType = "video/x-ms-asf"
case ".avi"
ContentType = "video/avi"
case ".doc"
ContentType = "application/msword"
case ".zip"
ContentType = "application/zip"
case ".xls"
ContentType = "application/vnd.ms-excel"
case ".gif"
ContentType = "image/gif"
case ".jpg"
case ".jpeg"
ContentType = "image/jpeg"
case ".wav"
ContentType = "audio/wav"
case ".mp3"
ContentType = "audio/mpeg3"
case ".mpg"
case ".mpeg"
ContentType = "video/mpeg"
case ".rtf"
ContentType = "application/rtf"
case ".htm"
case ".html"
ContentType = "text/html"
case ".txt"
ContentType = "text/plain"
case else
ContentType = "application/octet-stream"
End Select
s.LoadFromFile(filepath)
If Err <> 0 Then
Response.Write Err.description
Err.Clear
Response.End
End If
Response.CharSet = "UTF-8"
Response.AddHeader "Content-Disposition", "attachment; filename=""" & filename & """;"
Response.AddHeader "Content-Length", filesize
Response.ContentType = ContentType
'只有这里有点不同,其实上面的JS版里面也可以直接用:
'for(var i = 0; i < Math.ceil(filesize / bufferSize); i++)
'{
' Response.BinaryWrite(s.Read(bufferSize));
'}
'也是一样的,只不过按JScript版本那样写是一种好习惯(规范一些),因为ASP里面的ADO有兼容,如果游标超出FILE_POS会自动读取至结尾,ADO的游标也会自动前进,但其它有些语言就不会这样了,会出错,在这里就直接偷懒吧
Dim i, bufferSize : bufferSize = 1048576
s.Position = 0
'直接偷懒
For i = 0 To filesize \ bufferSize
Response.BinaryWrite(s.Read(bufferSize))
Next
'Response.Clear();
Set file = Nothing
Set fso = Nothing
s.Close
Set s = Nothing
End Sub
%>
欢迎转载,但转载请注意保留原博客及作者信息
作者:JC
MSN:rot-apple@hotmail.com
Skype:ctv_jcyuan
博客:http://www.jc-space.com/blog
[本日志由 admin 于 2009-07-02 09:48 AM 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: ASP BinaryWrite 发送大文件 Response.BinaryWrite
文章来自: 本站原创
Tags: ASP BinaryWrite 发送大文件 Response.BinaryWrite 评论: 0 | 引用: 0 | 查看次数: -
发表评论
上一篇
下一篇![订阅所有[其它语言]的日志](images/rss.png)
