最近尝试写了一个下载类的网站,是用ASP写的,但是ASP语言有个挺致命的缺点,用流对象读取文件时,是将文件一次性读入内存的,文件小倒无所谓了,可是如果文件很大呢? 你可能也想到了,内存会被大量占用,基至导致内存不足而报错!
本来我已经想到另外一个方法了,就是用APS.net来编写一个实现下载大文件功能的ASPX页面,然后用ASP调用ASPX页面即可,并且也已经实现了;
不过,能不能利用VB组件来实现ASP的下载大文件功能呢,于是在网上找了一圈,但是找到的一些组件都不满足要求,接着自已历经一月之久,终于完成了以下的ASP大文件下载的VB组件。
1.如何在VB中调用ASP对象
在VB工程中引用“COM+ Services Type Library”、“Microsoft Active Server Pages Object library”、“Microsoft Active Server Pages ObjectContext Object Library”;一般情况是需要安装IIS的,在安装完成后,上面的两个ASP控件就会存在了;
2.VB组件代码
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 3 'UsesTransaction
END
Attribute VB_Name = "bkRead"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True
Option Explicit '强制显式声明模块中的所有变量。
Private Const OFS_MAXPATHNAME = 128
Private Type OFSTRUCT
cBytes As Byte
fFixedDisk As Byte
nErrCode As Integer
Reserved1 As Integer
Reserved2 As Integer
szPathName(OFS_MAXPATHNAME) As Byte
End Type
Private Declare Function OpenFile Lib "kernel32" (ByVal lpFileName As String, lpReOpenBuff As OFSTRUCT, ByVal wStyle As Long) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const OF_READ = &H0
'Private Const FILE_SHARE_READ = &H1
'Private Const MAXLONG = &H7FFFFFFF '2147483647,这是最大的长整型数
Private Const FILE_BEGIN = &H0
Private Const BU_SIZE = 1048576
Private mBytes() As Byte
Dim m_objResponse As Response
Private Sub Class_Initialize()
Dim objContext As ObjectContext
Set objContext = GetObjectContext()
Set m_objResponse = objContext("Response")
End Sub
Public Function vbDownload(ByVal filePath As String, ByVal ciShu As Integer) As Integer
On Error GoTo Err
Dim fHandle As Long
Dim OF As OFSTRUCT
fHandle = OpenFile(filePath, OF, OF_READ)
If fHandle <> -1 Then
Dim nSize As Long
nSize = GetFileSize(fHandle, 0)
If nSize > 0 Then
Dim Rtn As Long
Dim Rrtn As Long
Dim filePos As Long
Dim i As Long
Rtn = BU_SIZE
filePos = ciShu * Rtn
ReDim mBytes(Rtn - 1) As Byte
SetFilePointer fHandle, filePos, 0, FILE_BEGIN '设置文件指针
ReadFile fHandle, mBytes(0), Rtn, Rrtn, 0 '分块读取
If Rrtn <> Rtn Then
ReDim Preserve mBytes(Rrtn - 1) As Byte
vbDownload = 0 '0表示到文件结尾了
m_objResponse.BinaryWrite mBytes()
Else
vbDownload = 1 '1表示未到结尾
m_objResponse.BinaryWrite mBytes()
End If
End If
CloseHandle fHandle
End If
If Err Then
Err.Clear
CloseHandle fHandle
vbDownload = -1 '出错均为-1
End If
Exit Function
Err:
CloseHandle fHandle
vbDownload = -1 '出错均为-1
End Function
3.ASP调用方法
先由上面的bkIO工程,生成bkIO.dll文件,然后运行“regsvr32 bkIO.dll”注册我们刚编写的组件,接下来编写测试的ASP代码:
<%
Server.ScriptTimeout = 1800 '超时30分钟
flpath="e:\Windows XP Professional-s004.vmdk" '用于试验的大文件
Set fso=Server.CreateObject("Scripting.FileSystemObject")
Set fl=fso.getfile(flpath)
flsize=fl.size '获取大文件的大小
flName=fl.name '获取大文件的名字
Set fl=Nothing
Set fso=Nothing
Set myzj = Server.CreateObject("bkIO.bkRead") '创建自定义组件的对象
if isobject(myzj) then '判断组件是否安装成功
response.Write "<p>服务器支持: √ </p>"
else
response.Write "<p>服务器不支持:× </p> "
end if
Response.Clear
Response.Buffer = true
Response.AddHeader "content-type", "application/octet-stream"
Response.AddHeader "Content-Disposition", "attachment;filename=" & flName
Response.AddHeader "Content-Length",flsize
dim flag:flag=-1
dim i:i=CLng(0)
do '开始读写
flag=myzj.vbDownload(flpath,i)
Response.Flush
i=i+1 '依次分块向后读写
loop until flag=0 '直至读到文件结尾才结束
set myzj=nothing
Response.End
%>
4.修改IIS超时设置
大文件的下载时间一般比较长,我们需要修改IIS的超时设置:
1.IIS管理器->本机名称->ASP->限制设置->脚本超时 00:30:00
2.IIS管理器->本机名称->ASP->限制设置->响应缓冲限制 2147483647
3.IIS管理器->Default Web Site->高级设置->连接限制 1800s
也可以试试将脚本添加到ASP页:Server.ScriptTimeout=1800;30分钟
5.不足之处:下载文件时,没有下载进度条的逐渐加长,只有下载完成时进度条的猛然全满?如果有哪位仁兄知其缘由,欢迎不吝赐教啊!(已解决!)
6.其它说明:以上只是利用了Windows API的读方法,如果需要写方法,请参考https://blog.csdn.net/bmjhappy/article/details/81091694和https://www.jianshu.com/p/787fde709ca0
联系QQ:252089877