zoukankan      html  css  js  c++  java
  • InternetReadFile如何正确读取二进制文件

     
     
    手上的一个VB项目(过程中发现,.Net果然是好啊),需要在一个ActiveX中实现HTTP下载功能,我是采用InternetreadFile这个API来实现,一开始的代码我是这么写的
     
    Function Gethttpdownload(sUrl As StringAs boolen
     
    Dim s As String
    Dim hOpen As Long
    Dim hOpenUrl As Long
    Dim bDoLoop As Boolean
    Dim bRet As Boolean
    Dim sReadBuffer As String * 2048
    Dim lNumberOfBytesRead As Long
    hOpen 
    = InternetOpen(scUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
    hOpenUrl 
    = InternetOpenUrl(hOpen, sUrl, vbNullString, 0, INTERNET_FLAG_RELOAD, 0)
     bDoLoop 
    = True
     
    Do While bDoLoop
      sReadBuffer 
    = vbNullString
      bRet 
    = InternetReadFile(hOpenUrl, sReadBuffer, Len(sReadBuffer), lNumberOfBytesRead)
      s 
    = s & Left$(sReadBuffer, lNumberOfBytesRead)
      
    If Not CBool(lNumberOfBytesRead) Then bDoLoop = False
      
    Loop
    FileName 
    = "E:\BitSpirit\Torrent\121212.torrent"
    F1 = FreeFile
    Open FileName 
    For Binary As F1
    Put F1, , s
    Close F1
     
    If hOpen <> 0 Then InternetCloseHandle (hOpen)
     Gethttpdownload 
    = true
     
    End Function
     
    上面方法,用来获取服务器上的文本类型的文件一点问题,都没有,但是用来下载二进制文件的时候 就出现问题了,里面的数据怎么也不对,研究了下载下来的文件后发现,问题外话应该是在接收数据的变量是个STRING的定长字符串上。但是在网上查了好久,甚至M$ MSDN上的一个用VB来实现下载的程也是用 string类型来接收数据的而且网上的代码写法,基本上也都是这个样,好来才好现,都是从MSDN上的哪个例程上演变过来的.
           我想如果能用一个byte数组来代替定长字符串,哪可能就没有问题了,但是查看了一个VB 对Internetreadfile的申明
    Public Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Integer
    发现其定义ByVal sBuffer As String 看来只能用String了,在网上查找过程中,发现人家用VC写的程序中这人参数可以是其它的,所以查看了一下Internetreadfile的原型。发现的确可以, 所以我把internetreadfile的定义修改了一下,为了通用,我为新的internetreadfile定义了一个别名。Internetreadfilebyte申明如下:
    Public Declare Function InternetReadFileByte Lib "wininet.dll" Alias "InternetReadFile" (ByVal hFile As Long, ByRef sBuffer As Byte, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Integer
    试了一下的确可以,重新修改函数,(在这过程中发现,如果要取到正确数据,还必须取得文件大小。所以增加了HttpQueryInfo的定义)最后完整的函数
    Function FileDownload(sUrl As Variant) As Boolean
            
    Dim b(99As Byte
            
    Dim EndByte() As Byte
            
    Dim s As String
            
    Dim hOpen As Long
            
    Dim hOpenUrl As Long
            
    Dim bDoLoop As Boolean
            
    Dim bRet As Boolean
            
    Dim bbuffer As Byte
            
    Dim sReadBuffer As String
            
    Dim FileName As String
            
    Dim lNumberOfBytesRead As Long
            
    Dim F1 As Integer
            
    Dim strsize As String
            
    Dim size As Long
            strsize 
    = String$(1024" ")
     
            F1 
    = FreeFile
            stTotal 
    = vbNullString
            FileName 
    = "E:\BitSpirit\Torrent\121212.torrent"
            Open FileName For Binary As F1
            hOpen 
    = InternetOpen(scUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
            hOpenUrl 
    = InternetOpenUrl(hOpen, sUrl, vbNullString, 0, INTERNET_FLAG_RELOAD, 0)
            bDoLoop 
    = True
            HttpQueryInfo hOpenUrl, HTTP_QUERY_CONTENT_LENGTH 
    Or HTTP_QUERY_FLAG_NUMBER, ByVal strsize, Len(strsize), 0
            size 
    = CLng(Trim(strsize))
             
    For j = 1 To size \ 100
              bDoLoop 
    = InternetReadFileByte(hOpenUrl, b(0), 100, lNumberOfBytesRead)
     
              Put F1, , b
              
    If Not CBool(lNumberOfBytesRead) Then Exit For
             
    Next
            
    If size Mod 100 <> 0 Then
            tmp 
    = (size Mod 100- 1
            
    ReDim EndByte(tmp)
              bDoLoop 
    = InternetReadFileByte(hOpenUrl, EndByte(0), tmp + 1, lNumberOfBytesRead)
              Put F1, , EndByte
            
    End If
     
             
    If hOpenUrl <> 0 Then InternetCloseHandle (hOpenUrl)
             
    If hOpen <> 0 Then InternetCloseHandle (hOpen)
     
            Close #
    1
            FileDownload 
    = True
    End Function
    测试了一下,完全成功:)




    Creative Commons License
    作品平波创作,采用知识共享署名 2.5 中国大陆许可协议进行许可。
  • 相关阅读:
    设置跨域
    Vs自定nuget push菜单
    VS IIS Express 支持局域网访问
    字符串GZIP压缩解压
    C# 使用 protobuf 进行对象序列化与反序列化
    RabbitMQ
    如果调用.net core Web API不能发送PUT/DELETE请求怎么办?
    log4net配置使用
    redis实现消息队列
    Error-the resource is not on the build path of a java project
  • 原文地址:https://www.cnblogs.com/9527/p/159108.html
Copyright © 2011-2022 走看看