отправить файл и параметр HTTP Post с помощью VBS - PullRequest
0 голосов
/ 10 мая 2018

Я новичок в работе с протоколом HTTP и некоторое время не работал с VBS. У меня проблема с отправкой параметра и файла загрузки в веб-сервис. Я просто не понимаю, что это за код. Ниже приведена часть кода.

     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 = "publishing = 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

1 Ответ

0 голосов
/ 06 ноября 2018

Я нашел решение. Это была моя логика:

с curl Вы можете отправить файл + параметры с:

curl -XPOST '127.0.0.1:8000' -F 'file=@/Users/luca/Desktop/img.png' -F 'id=123456'

В этом случае вы можете увидеть:

  • IP = 127.0.0.1 (localhost)
  • Порт = 8000
  • Имя файла = img.png
  • Parameter = "id" со значением 123456

Если вы используете netcat в режиме прослушивания, подобном этому ...

nc -l -p 8000

Это означает, что он прослушивает что-либо на порту 8000 локального хоста = 127.0.0.1 (я использую версию Netcat для Mac. Возможно, вам придется изменить некоторые параметры, чтобы она работала так).

Итак: запустите 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;"

(граница является своего рода разделителем. Проверьте это в Google)

Затем вы можете построить тело запроса 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:\Users\Luca\Desktop\i.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:\Users\Luca\Desktop\i.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) И двоичный файл ...

ПРИМЕЧАНИЕ. С помощью Content-type: application / octet-stream вы также можете отправить неизвестное расширение файла

...