You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB6如何获取ESBox设备的底层电力数据而非HTML页面?

问题分析与解决方案

核心问题出在请求头差异和身份验证处理方式上:

1. 为什么Firefox能拿到数据,VB6不行?

  • Firefox访问API时会自动发送符合预期的Accept请求头(比如application/json或text/plain),服务器据此返回原始数据;
  • VB6默认网络组件(如URLDownloadToFile、Inet控件)发送的Accept头通常是text/html, */*,服务器认为你需要网页,因此返回HTML内容;
  • 另外,URL中esbox:esbox@esbox这种Basic Auth写法,部分旧Windows组件处理不规范,导致身份验证失败,服务器返回HTML登录页或错误页。

2. 解决步骤

步骤1:手动构造请求头

必须明确告诉服务器你需要原始数据,添加Accept: application/json(或text/plain,取决于ESBox API的返回格式),同时手动处理Basic Auth。

步骤2:用WinINet API实现可控请求

WinINet比URLDownloadToFile更灵活,能精确控制请求参数,以下是完整VB6示例代码:

' WinINet API声明
Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" (ByVal hInternetSession As Long, ByVal sServerName As String, ByVal nServerPort As Integer, ByVal sUsername As String, ByVal sPassword As String, ByVal lService As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
Private Declare Function HttpOpenRequest Lib "wininet.dll" Alias "HttpOpenRequestA" (ByVal hConnect As Long, ByVal sVerb As String, ByVal sObjectName As String, ByVal sVersion As String, ByVal sReferer As String, ByVal plpszAcceptTypes As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
Private Declare Function HttpAddRequestHeaders Lib "wininet.dll" Alias "HttpAddRequestHeadersA" (ByVal hHttpRequest As Long, ByVal sHeaders As String, ByVal dwHeadersLength As Long, ByVal dwModifiers As Long) As Boolean
Private Declare Function HttpSendRequest Lib "wininet.dll" Alias "HttpSendRequestA" (ByVal hHttpRequest As Long, ByVal sHeaders As String, ByVal dwHeadersLength As Long, ByVal sOptional As String, ByVal dwOptionalLength As Long) As Boolean
Private Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumberOfBytesToRead As Long, lNumberOfBytesRead As Long) As Boolean
Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer

' Base64编码函数(用于Basic Auth)
Private Function Base64Encode(sText As String) As String
    Dim bData() As Byte
    bData = StrConv(sText, vbFromUnicode)
    Base64Encode = EncodeBase64(bData)
End Function

Private Function EncodeBase64(bData() As Byte) As String
    Dim sBase64 As String
    Dim lLen As Long, lGroup As Long
    Dim bGroup(2) As Byte, lGroupBits As Long
    Dim s64Chars As String
    s64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    
    lLen = UBound(bData) + 1
    For lGroup = 0 To (lLen \ 3) - 1
        bGroup(0) = bData(lGroup * 3)
        bGroup(1) = bData(lGroup * 3 + 1)
        bGroup(2) = bData(lGroup * 3 + 2)
        lGroupBits = (bGroup(0) * &H10000) + (bGroup(1) * &H100) + bGroup(2)
        sBase64 = sBase64 & Mid(s64Chars, (lGroupBits \ &H4000) + 1, 1)
        sBase64 = sBase64 & Mid(s64Chars, ((lGroupBits \ &H100) Mod &H40) + 1, 1)
        sBase64 = sBase64 & Mid(s64Chars, ((lGroupBits \ &H4) Mod &H40) + 1, 1)
        sBase64 = sBase64 & Mid(s64Chars, (lGroupBits Mod &H4) * &H10 + 1, 1)
    Next lGroup
    
    Select Case lLen Mod 3
        Case 1
            bGroup(0) = bData(lLen - 1)
            lGroupBits = bGroup(0) * &H10000
            sBase64 = sBase64 & Mid(s64Chars, (lGroupBits \ &H4000) + 1, 1)
            sBase64 = sBase64 & Mid(s64Chars, ((lGroupBits \ &H100) Mod &H40) + 1, 1)
            sBase64 = sBase64 & "=="
        Case 2
            bGroup(0) = bData(lLen - 2)
            bGroup(1) = bData(lLen - 1)
            lGroupBits = (bGroup(0) * &H10000) + (bGroup(1) * &H100)
            sBase64 = sBase64 & Mid(s64Chars, (lGroupBits \ &H4000) + 1, 1)
            sBase64 = sBase64 & Mid(s64Chars, ((lGroupBits \ &H100) Mod &H40) + 1, 1)
            sBase64 = sBase64 & Mid(s64Chars, ((lGroupBits \ &H4) Mod &H40) + 1, 1)
            sBase64 = sBase64 & "="
    End Select
    EncodeBase64 = sBase64
End Function

' 获取ESBox数据的核心函数
Private Function GetESBoxData() As String
    Dim hOpen As Long, hConnect As Long, hRequest As Long
    Dim sBuffer As String * 1024
    Dim lBytesRead As Long
    Dim sResult As String
    Dim sAuthHeader As String
    
    ' 初始化WinINet会话
    hOpen = InternetOpen("VB6 ESBox Client", 1, vbNullString, vbNullString, 0)
    If hOpen = 0 Then Exit Function
    
    ' 连接到ESBox服务器
    hConnect = InternetConnect(hOpen, "esbox", 80, vbNullString, vbNullString, 3, 0, 0)
    If hConnect = 0 Then
        InternetCloseHandle hOpen
        Exit Function
    End If
    
    ' 创建HTTP GET请求
    hRequest = HttpOpenRequest(hConnect, "GET", "/api/devices", "HTTP/1.1", vbNullString, 0, &H80000000, 0)
    If hRequest = 0 Then
        InternetCloseHandle hConnect
        InternetCloseHandle hOpen
        Exit Function
    End If
    
    ' 添加请求头:Accept和Authorization
    sAuthHeader = "Authorization: Basic " & Base64Encode("esbox:esbox") & vbCrLf
    sAuthHeader = sAuthHeader & "Accept: application/json" ' 根据实际数据格式调整,比如text/plain
    
    HttpAddRequestHeaders hRequest, sAuthHeader, Len(sAuthHeader), &H20
    
    ' 发送请求
    If HttpSendRequest(hRequest, vbNullString, 0, vbNullString, 0) Then
        ' 读取返回数据
        Do While InternetReadFile(hRequest, sBuffer, 1024, lBytesRead)
            If lBytesRead = 0 Then Exit Do
            sResult = sResult & Left(sBuffer, lBytesRead)
        Loop
    End If
    
    ' 清理资源
    InternetCloseHandle hRequest
    InternetCloseHandle hConnect
    InternetCloseHandle hOpen
    
    GetESBoxData = sResult
End Function

' 测试按钮点击事件
Private Sub cmdGetData_Click()
    Dim sData As String
    sData = GetESBoxData()
    If sData <> "" Then
        rtBox.Text = sData
        ' 可选:保存到文件
        Open "e:\esbox\esbox5\devices.txt" For Output As #1
        Print #1, sData
        Close #1
    Else
        MsgBox "获取数据失败"
    End If
End Sub

3. 关键细节说明

  • Base64编码:Basic Auth需要把用户名:密码转换成Base64字符串,添加到Authorization头中,避免URL格式的兼容性问题;
  • Accept头:必须和Firefox发送的一致,可以用F12开发者工具查看Firefox的请求头(Network面板),把对应的Accept值复制到代码中;
  • WinINet标志位:&H80000000表示忽略重定向(如果ESBox有重定向到HTML页的情况,这个设置能避免被跳转);
  • 端口号:示例用的是80端口(HTTP默认),如果ESBox用的是其他端口,需要修改InternetConnect中的端口参数。

4. 验证方法

  1. 用Firefox打开esbox/api/devices,按F12打开开发者工具,切换到Network面板;
  2. 刷新页面,找到对应的请求,查看Request Headers中的Accept和Authorization值;
  3. 确保代码中的请求头和Firefox的完全一致,这样就能保证服务器返回相同的响应。

内容的提问来源于stack exchange,提问作者Argusy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 01:30:04