使用 VBS 发送文件和参数 HTTP Post



我是使用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( 和二进制文件...

注意:使用内容类型:应用程序/八位字节流,您也可以发送未知的文件扩展名

最新更新