我正在嘗試使用 VBA 將檔案上傳到 Web 服務,遵循通過 Web 瀏覽器上傳檔案時發送的表單資料多部分結構,但是我收到了“400:無效的多部分有效負載格式”回應,盡管發送(從什么我可以說)請求中的有效負載相同。
對于我的測驗用例,我創建了一個名為 test.txt 的 txt 檔案,其中包含“TestContents”。我已經使用網路瀏覽器上傳了這個檔案,并且也嘗試過使用 VBA(如下所示)。花一些時間將來自 Chrome 的有效負載與我自己的 VBA 生成的有效負載進行比較,我看不出任何差異。
我正在使用以下代碼創建多部分有效負載并將其發送到 Web 服務(URL 部分混淆),并使用以下問題幫助重新撰寫了幾次以解決此問題:[https:/ /stackoverflow.com/questions/50110601/upload-a-picture-to-file-io-http-post-in-vba]
(對于內部的任何混亂,我深表歉意 - 我已經改變并重新撰寫了很長一段時間,所以可能會有一些不整潔)
Private Function toArray(inData As String)
Dim objADODB As Object: Set objADODB = CreateObject("ADODB.Stream")
objADODB.Type = 2
objADODB.Charset = "_autodetect"
objADODB.Open
objADODB.WriteText (inData)
objADODB.Position = 0
objADODB.Type = 1
toArray = objADODB.Read()
Set objADODB = Nothing
End Function
Private Function readBinary(filePath As String)
Dim objADODB As Object: Set objADODB = CreateObject("ADODB.Stream")
objADODB.Type = 1
objADODB.Open
objADODB.LoadFromFile filePath
readBinary = objADODB.Read
objADODB.Close
Set objADODB = Nothing
End Function
Public Sub sendDocument(ByVal inID As String, ByVal tags As String, ByVal docContentType As String, ByVal docFilePath As String)
Dim objADODB As Object
Dim objHTTP As Object
Dim boundary As String: boundary = "----WebKitFormBoundaryeeYChAY7UlBEI63d" 'Set like this so i can debug like-for-like with browser payload
Dim docFileName As String: docFileName = Mid(docFilePath, InStrRev(docFilePath, "\") 1)
'(structure is file, material, tags if there are any)
Set objADODB = CreateObject("ADODB.Stream")
With objADODB
.Type = 1
.Open
.Write toArray("--" & boundary & Chr(10))
.Write toArray("Content-Disposition: form-data; name=""file""; filename=""" & docFileName & """" & Chr(10) & _
"Content-Type: " & docContentType & Chr(10) & Chr(10))
.Write readBinary(docFilePath)
.Write toArray(Chr(10) & "--" & boundary & Chr(10))
.Write toArray("Content-Disposition: form-data; name=""material""" & Chr(10) & Chr(10) & inID & Chr(10))
If tags <> "" Then .Write toArray("Content-Disposition: form-data; name=""tags""" & Chr(10) & Chr(10) & tags & Chr(10))
.Write toArray("--" & boundary & "--")
.Position = 0
End With
If Not validateID(inID) Then
MsgBox ("ID must be 4-5 digits long")
Exit Sub
End If
If auth = "" Then
MsgBox "Login is required. Click OK to log in"
Call getAuth
End If
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
With objHTTP
.Open "POST", "https://xxx.xxx/hapi/document", False
.setRequestHeader "Authorization", auth
.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & boundary
.send (objADODB.Read())
MsgBox .responseText
End With
bStatusOK = objHTTP.status = 200
If objHTTP.status = 401 Then
MsgBox ("Login is invalid/expired. Please reauthenticate")
Call getAuth
End If
End Sub
當查看請求的表單資料時,上面產生的有效載荷與 Chrome 的檢查器視窗中存在的有效載荷相同,即:
------WebKitFormBoundaryeeYChAY7UlBEI63d
Content-Disposition: form-data; name="file"; filename="Test.txt"
Content-Type: text/plain
TestContents
------WebKitFormBoundaryeeYChAY7UlBEI63d
Content-Disposition: form-data; name="material"
16145
------WebKitFormBoundaryeeYChAY7UlBEI63d--
我開始懷疑它沒有正確編碼。我注意到瀏覽器呼叫使用標題
Accept-Encoding: gzip, deflate, br
..當我嘗試復制此型別或任何單一型別(br 除外)時,我仍然收到相同的訊息,但以 VBA 本地視窗無法理解的格式回復。我已經成功使用其他 POST 和 PUT 請求發送 JSON 或文本有效負載,而無需指定 Accept-Encoding,因此我不確定這是否是繼續前進的正確路徑。
如果有人能夠為此提供一些幫助,我將不勝感激。
謝謝!
uj5u.com熱心網友回復:
如果您有標簽引數,它將缺少起始邊界。
If tags <> "" Then
.Write toArray("--" & boundary & vbCrLf)
.Write toArray("Content-Disposition: form-data; name=""tags""" & vbCrLf & vbCrLf & tags & vbCrLf)
End If
uj5u.com熱心網友回復:
感謝 CDP1802 的評論解決了!需要 VbCrLf 而不是 Chr(10)。
構建表單資料的作業部分現在看起來像:
Set objADODB = CreateObject("ADODB.Stream")
With objADODB
.Type = 1
.Open
.Write toArray("--" & boundary & vbCrLf)
.Write toArray("Content-Disposition: form-data; name=""file""; filename=""" & docFileName & """" & vbCrLf & _
"Content-Type: " & docContentType & vbCrLf & vbCrLf)
.Write readBinary(docFilePath)
.Write toArray(vbCrLf & "--" & boundary & vbCrLf)
.Write toArray("Content-Disposition: form-data; name=""material""" & vbCrLf & vbCrLf & inID & vbCrLf)
If tags <> "" Then
.Write toArray("--" & boundary & vbCrLf)
.Write toArray("Content-Disposition: form-data; name=""tags""" & vbCrLf & vbCrLf & tags & vbCrLf)
End If
.Write toArray("--" & boundary & "--")
.Position = 0
End With
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/386809.html
上一篇:從表A到表B傳輸隨機列值
下一篇:在代碼中間宣告變數有什么風險?
