用VB编写ASP组件,实现大文件分块读取和下载

        最近尝试写了一个下载类的网站,是用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/81091694https://www.jianshu.com/p/787fde709ca0

联系QQ:252089877

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值