Я нашел решение. Это была моя логика:
с 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 вы также можете отправить неизвестное расширение файла