我是使用HTTP协议的新手,已经有一段时间没有使用VBS了。 我遇到的问题是将参数和上传文件发送到 Web 服务。 我只是不明白某些代码是什么。下面是代码的一部分。
With CreateObject("MSXML2.ServerXMLHTTP")
.setOption 2, 13056 'http://msdn.microsoft.com/en-
us/library/ms763811(v=VS.85).aspx
.SetTimeouts 0, 60000, 300000, 300000
.Open "POST",
"https://192.168.100.100/api/import_file_here.json", False
.SetRequestHeader "Content-type", "multipart/form-data; boundary=" &
strBoundary 'THIS SEND THE FILE
.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" '
THIS SEND THE PARAMETER.
.Send bytPD ' sends param
.Send bytPayLoad '''SEND FILE
我知道我不能使用.发送两次。 我相信我需要在下面的代码块中进行更改。
With CreateObject("ADODB.Stream")
.Mode = 3
.Charset = "Windows-1252"
.Open
.Type = 2
.WriteText "--" & strBoundary & vbCrLf
'.WriteText "Content-Disposition: form-data; name=""file""; filename=""" &
strFile & """" & vbCrLf
.WriteText "Content-Disposition: form-data; name=""file"";
publication=""moveit_test_pub"""
'.WriteText "Content-Type: """ & strContentType & """" & vbCrLf & vbCrLf
.Position = 0
.Type = 1
.Write bytData
.Position = 0
.Type = 2
.Position = .Size
.WriteText vbCrLf & "--" & strBoundary & "--"
.Position = 0
.Type = 1
bytPayLoad = .Read
bytPD = "publication=moveit_test_pub"
bytPD = "publication=moveit_test_pub" 是我需要的文件上传参数。 我只是不确定如何将其添加到上面的块中。 如果那是我应该改变的地方。 我将在下面发布整个代码以供参考。 感谢您的帮助!
strFilePath = "C:SCAudience_TEST5.txt"
UploadFile strFilePath, strUplStatus, strUplResponse
MsgBox strUplStatus & vbCrLf & strUplResponse
Sub UploadFile(strPath, strStatus, strResponse)
Dim strFile, strExt, strContentType, strBoundary, bytPD, bytData,
bytPayLoad
On Error Resume Next
With CreateObject("Scripting.FileSystemObject")
If .FileExists(strPath) Then
strFile = .GetFileName(strPath)
strExt = .GetExtensionName(strPath)
Else
strStatus = "File not found"
Exit Sub
End IF
End With
With CreateObject("Scripting.Dictionary")
.Add "txt", "text/plain"
.Add "html", "text/html"
.Add "php", "application/x-php"
.Add "js", "application/x-javascript"
.Add "vbs", "application/x-vbs"
.Add "bat", "application/x-bat"
.Add "jpeg", "image/jpeg"
.Add "jpg", "image/jpeg"
.Add "png", "image/png"
.Add "exe", "application/exe"
.Add "doc", "application/msword"
.Add "docx", "application/vnd.openxmlformats-
officedocument.wordprocessingml.document"
.Add "xls", "application/vnd.ms-excel"
.Add "xlsx", "application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet"
strContentType = .Item(LCase(strExt))
End With
If strContentType = "" Then
strStatus = "Invalid file type"
Exit Sub
End If
With CreateObject("ADODB.Stream")
.Type = 1
.Mode = 3
.Open
.LoadFromFile strPath
If Err.Number <> 0 Then
strStatus = Err.Description & " (" & Err.Number & ")"
Exit Sub
End If
bytData = .Read
bytPD = "publication=moveit_test_pub"
End With
strBoundary = String(6, "-") & Replace(Mid(CreateObject("Scriptlet.TypeLib").Guid, 2, 36), "-", "")
With CreateObject("ADODB.Stream")
.Mode = 3
.Charset = "Windows-1252"
.Open
.Type = 2
.WriteText "--" & strBoundary & vbCrLf
' .WriteText "Content-Disposition: form-data; name=""file""; filename=""" & strFile & """" & vbCrLf
.WriteText "Content-Disposition: form-data; name=""file""; publication=""moveit_test_pub"""
'.WriteText "Content-Type: """ & strContentType & """" & vbCrLf & vbCrLf
.Position = 0
.Type = 1
.Write bytData
.Position = 0
.Type = 2
.Position = .Size
'' .WriteText vbCrLf & "--" & strBoundary & "--"
.Position = 0
.Type = 1
bytPayLoad = .Read
bytPD = "publication=moveit_test_pub"
End With
With CreateObject("MSXML2.ServerXMLHTTP")
.setOption 2, 13056 'http://msdn.microsoft.com/en-us/library/ms763811(v=VS.85).aspx
.SetTimeouts 0, 60000, 300000, 300000
.Open "POST", "https://192.168.100.100/api/import_file_here.json", False
.SetRequestHeader "Content-type", "multipart/form-data; boundary=" & strBoundary 'THIS SEND THE FILE IF BOTH SELECTED SEND PARM AND TEXT OF FILE
.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" ' THIS SEND THE PARAMETER.
''' .Send bytPD ' sends param
' .SetRequestHeader "Content-type", "multipart/form-data; boundary=" & strBoundary 'NEW LINE
.Send bytPayLoad '''SEND FILE
MsgBox bytPD
If Err.Number <> 0 Then
strStatus = Err.Description & " (" & Err.Number & ")"
Else
strStatus = .StatusText & " (" & .Status & ")"
End If
If .Status = "400" Then strResponse = .ResponseText
If .Status = "401" Then strResponse = .ResponseText
If .Status = "200" Then strResponse = .ResponseText
End With
End Sub
我找到了解决方案。这是我的逻辑:
使用curl,您可以发送文件 + 参数:
curl -XPOST '127.0.0.1:8000' -F 'file=@/Users/luca/Desktop/img.png' -F 'id=123456'
在本例中,您可以看到:
- IP = 127.0.0.1(本地主机(
- 端口 = 8000
- 文件名 = img.png
- 参数 = 值为 123456 的"id">
如果您像这样在侦听模式下使用 netcat...
nc -l -p 8000
这意味着它正在侦听本地主机 = 127.0.0.1 的端口 8000 上的任何内容(我使用的是 Mac 版本的 Netcat。您可能需要更改一些参数以使其像这样工作(。
所以:在侦听模式下启动netcat,启动上一个curl命令,您将看到整个POST数据包。现在你知道它是如何制作的了。它将看起来像这样:
POST / HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: curl/7.54.0
Accept: */*
Content-Length: 427
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------60cd44468072da0e
--------------------------60cd44468072da0e
Content-Disposition: form-data; name="file"; filename="img.png"
Content-Type: application/octet-stream
?PNG
IHDR
??w&sRGB???gAMA??
?a pHYs??(J?IDAT(Scd``??D&(MU?
?bg?ܞ?IEND?B`?
--------------------------60cd44468072da0e
Content-Disposition: form-data; name="id"
123456
--------------------------60cd44468072da0e--
现在您知道了工作数据包是如何制作的,您可以复制它。
对于标头,请使用:httpServer.SetRequestHeader "Content-type", "multipart/form-data; boundary=------------------------2deddc24cb2a8ca2;"
(边界是一种分隔符。在谷歌上检查(
然后,您可以构建 POST 请求的正文:
body = "--" & "------------------------2deddc24cb2a8ca2" & vbCrLf & _
"Content-Disposition: form-data; name=""file""; filename=""" & objFSO.GetFileName(objFile) & """" & vbCrLf & _
"Content-Type: application/octet-stream" & vbCrLf & vbCrLf & _
FILE_CONTENT & vbCrLf & _
"--" & "------------------------2deddc24cb2a8ca2" & vbCrLf & _
"Content-Disposition: form-data; name=""id""" & vbCrLf & vbCrLf & _
ID & vbCrLf & _
"--" & "------------------------2deddc24cb2a8ca2" & "--" & vbCrLf & vbCrLf
注意:
- 在正文中,您可以看到每个边界的开头都有一个额外的"--">字符串(事实上我写了"--"和"------------------------2deddc24cb2a8ca2">(,在最后一个边界的末尾还有一个额外的"--"。
- 标头必须在 vbs 中的行尾包含";">,即使在上一个捕获的 POST 请求中不可见。我不知道为什么。
- 正文中的FILE_CONTENT变量是文件的内容
- 注意每个vbCrLf(行尾(,否则 POST 请求可能无效。
问题:您在下面发布的代码应该打开一个流,将正文的第一部分写为字符串,写入文件的 BINARY 内容,将正文的最后一部分写为字符串。
结合字符串和二进制数据,这对我不起作用:我只能发送二进制文件或仅发送文本文件。如果我将二进制内容转换为字符串,远程服务器将得到一个损坏的(不同的(文件......
示例(仅限二进制文件(:
Set stream = CreateObject("ADODB.Stream")
stream.Mode = 3
stream.Type = 1
stream.Open
stream.LoadFromFile("C:UsersLucaDesktopi.png")
Set objHttp = CreateObject("MSXML2.ServerXMLHTTP")
objHttp.Open "POST", "http://10.0.2.2:8000/", False
objHttp.Send stream.Read(stream.Size)
示例(仅限文本文件(
Set stream = CreateObject("ADODB.Stream")
stream.Mode = 3
stream.Type = 2
stream.Open
stream.LoadFromFile("C:UsersLucaDesktopi.txt")
readBinaryFile = stream.Read
requestBody = "--------------------------2deddc24cb2a8ca2" & vbCrLf & _
"Content-Disposition: form-data; name=""file""; filename=""" & objFSO.GetFileName(objFile) & """" & vbCrLf & _
"Content-Type: application/octet-stream" & vbCrLf & vbCrLf & _
readBinaryFile & vbCrLf & _
"--------------------------2deddc24cb2a8ca2" & vbCrLf & _
"Content-Disposition: form-data; name=""id""" & vbCrLf & vbCrLf & _
ID & vbCrLf & _
"--------------------------2deddc24cb2a8ca2--" & vbCrLf & vbCrLf
正如我告诉你的,如果你改变流。键入从 2 到 1(对于二进制(,您将结束发送损坏的文件。
我的解决方案是将参数作为额外的标头值发送: 例:
httpServer.Open "POST", "http://10.0.2.2:8000/", False
httpServer.SetRequestHeader "Content-type", "application/octet-stream;"
httpServer.SetRequestHeader "Id", ID
httpServer.Send stream.Read(stream.Size)
现在我可以发送参数 (Id( 和二进制文件...
注意:使用内容类型:应用程序/八位字节流,您也可以发送未知的文件扩展名