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. 验证方法
- 用Firefox打开
esbox/api/devices,按F12打开开发者工具,切换到Network面板; - 刷新页面,找到对应的请求,查看Request Headers中的
Accept和Authorization值; - 确保代码中的请求头和Firefox的完全一致,这样就能保证服务器返回相同的响应。
内容的提问来源于stack exchange,提问作者Argusy
相关产品推荐
相关产品推荐

