1 (изменено: wladkokopops, 2019-04-11 23:04:14)

Тема: AHK: Отправка фото на сервер

Проблема крутится вокруг Vk Api , сколько не искал и не читал, не могу понять как отправляется фото на сервер.
- Вызовите метод photos.getChatUploadServer, чтобы получить адрес для загрузки фото.
Вызвал метод, получил ответ ,получил адрес, окей.
-Передайте файл на адрес upload_url, полученный в предыдущем пункте, сформировав POST-запрос с полем file. Это поле должно содержать изображение в формате multipart/form-data.
Ага, а вот тут я встал в ступор,
допустим вот так я использую POST запрос:

whr := ComObjCreate("WinHttp.WinHttpRequest.5.1") 
whr.Open("POST", "URL", true) 
whr.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36") 
whr.SetRequestHeader("Content-Type","multipart/form-data") 
whr.Send() 
whr.WaitForResponse()

Но как передать сам файл?
Разве просто fileread? Или глупая идея?

2

Re: AHK: Отправка фото на сервер

whr.Send(binaryData)

3

Re: AHK: Отправка фото на сервер

MandarinKa02
Подробней можно?

whr.Send(binaryData)

это бинарный код отправить
а теперь как файл в бинарный перевести?

4

Re: AHK: Отправка фото на сервер

wladkokopops пишет:

а теперь как файл в бинарный перевести?

С трудом пытаюсь понять, что это значит.
https://autohotkey.com/docs/objects/File.htm#RawRead

5

Re: AHK: Отправка фото на сервер

MandarinKa02


fileread,jpeg,3.jpeg
binarydata := File.RawRead(jpeg, Bytes)

так?

6

Re: AHK: Отправка фото на сервер

Еще раз взываю о помощи!
Сколько бы не посылал вариаций Data файла,
приходит в ответ только META и пустой ответ photo!
как правильнее построить запрос на отсылку фото в лс?
Есть люди которые посылали уже файлы на сервер посредством AHK?

7

Re: AHK: Отправка фото на сервер

Вот тут по ссылке, вполне доступно рассказано.

При отправке данных методом POST с типом кодирования multipart/form-data, требуется:
1) В поле Content-Type указать строку вида

multipart/form-data; boundary=XXXXXXXXXX

Где "XXXXXXXXXX" является сгенерированной строкой разделителем данных (например: RaNdOmDeLiMiTeR). С помощью него серверная часть, получив из заголовка значение boundary и разбирая поток данных, может понять где закончились данные одного поля и начались данные другого поля.

В случае использования объекта WinHttpRequest / XmlHttpRequest это можно сделать методом SetRequestHeader

Object.SetRequestHeader("Content-Type","multipart/form-data; boundary=RaNdOmDeLiMiTeR")

2) Пример запроса:

--RaNdOmDeLiMiTeR
Content-Disposition: form-data; name="textField1"

test
--RaNdOmDeLiMiTeR
Content-Disposition: form-data; name="file1"; filename="image.jpg"
Content-Type: application/octet-stream

...[тело файла]....
--RaNdOmDeLiMiTeR--

Поясню.
а) Каждый блок данных начинается с разделителя boundary c начальными двумя дефисами (В данном случае "--RaNdOmDeLiMiTeR").
б) В тексте выше переданы два блока данных. Содержимое текстового поля "textField1" и тело файла с именем поля "file1"
Для передачи файловых полей после заголовка Content-Disposition вставляется ещё и заголовок Content-Type с указанием типа содержимого. Список значений для него можно посмотреть здесь

Для простоты можно использовать application/octet-stream, как универсальное значение при передаче двоичных данных.

в) В конце данных вставляется последний boundary и на его хвосте добавляются 2 дефиса. В нашем случае это будет --RaNdOmDeLiMiTeR--

3) По умолчанию текстовые данные формы передаются в кодировке UTF-8, а двоичные данные передаются как есть.

Вот как-то так.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

8 (изменено: wladkokopops, 2019-04-16 18:05:01)

Re: AHK: Отправка фото на сервер

Xameleon

ComObjError(false) 
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1") 
whr.Open("POST", uploadurl, true)
whr.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36") 
whr.SetRequestHeader("Content-Type","multipart/form-data; boundary=RaNdOmDeLiMiTeR")
whr.Send(oFile)
whr.WaitForResponse()
jsontext := % whr.ResponseText
msgbox % jsontext

Как в моём случае использовать делимитер?
Именно чтобы AHK не ругался на инородный код?

9

Re: AHK: Отправка фото на сервер

wladkokopops

1) Про сам AHK мне трудно сейчас подсказать, так как на ПК нет его среды для теста. К тому же кодил я на нём всего 1-2 раза в жизни и очень давно.

А в чём выражается "AHK ругается на инородный код" ?

2) Судя по коду, я не вижу, чтобы вы выполнили все необходимые действия с данными, которые отправляете на сервер.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

10

Re: AHK: Отправка фото на сервер

Xameleon
А можно подключить JS скрипт для отправки фото?
есть готовые варианты для VK?
Пусть AHK выкладывает UPLOAD_URL в текстовик, а JS по нему будет слать, и ответ обратно в текстовик.

11

Re: AHK: Отправка фото на сервер

wladkokopops. Хм... Ну пмсм, вариант крайне корявый + плюс наверняка придётся передавать cookie от объекта, которым Вы изначально авторизовывались в API. Но в принципе - можете попробовать.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

12

Re: AHK: Отправка фото на сервер

wladkokopops, учитесь пользоваться поиском.

13 (изменено: MandarinKa02, 2019-04-16 21:24:46)

Re: AHK: Отправка фото на сервер

*deleted*

14

Re: AHK: Отправка фото на сервер

wladkokopops, возможно Вам пригодится мой сэмпл загрузки файла на ресурс uploadfiles.io. Но сразу предупрежу он на JS. Для упрощения сборки запроса используется Windows Script Component (скриптовый компонент) webFormDataBuilder.wsc. Думаю, при желании, Вы можете использовать его из AHK.

Post's attachments

upload_sample.zip 137.71 kb, 6 downloads since 2019-04-16 

You don't have the permssions to download the attachments of this post.
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

15

Re: AHK: Отправка фото на сервер

Решил всё-таки тряхнуть стариной. Как вариант для AHK, наверное, можно так. Положите этот скрипт в папку с содержимым примера выше.


;Создание и настройка объекта для построения данных формы
form			:= ComObjGet("script:file:webFormDataBuilder.wsc")
form.method		:= "POST"
form.action		:= "https://up.uploadfiles.io/upload"
form.enctype	:= "multipart/form-data"

;Загрузка тела файла в буффер
fileName := "картинка.jpg"
;Открытие файла на чтение
file := FileOpen(fileName,"r")
if !IsObject(file)
{
    MsgBox Can't open "%FileName%" for reading.
    return
}

;Добавление тела файла в запрос
form.addFileField("file", "картинка.jpg", file.Read())
file.Close()

;Подготовка запроса к сервису
whr	:= ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.open(form.method, form.action, false)
whr.setRequestHeader("Content-Type",form.contentType)
whr.send(form.build())

;Загрузка объекта HTMLDocument
document := ComObjCreate("htmlfile")
;Установка режима совместимости
document.writeln("<meta http-equiv=""x-ua-compatible"" content=""IE=Edge""/>")
;Получение объекта JSON для разбора JSON данных
JSON := document.parentWindow.JSON

try {
    url := JSON.parse(whr.responseText).url
	ComObjCreate("WScript.Shell").Run(url)
} catch e {
	MsgBox JSON parsing failed !
}
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

16

Re: AHK: Отправка фото на сервер

Xameleon
Вот что у меня получилось, и что не получается в итоге.

Token := "TOKENVKONTAKTE"
ID := "94" ; ид беседы в которую загрузить фото, если меньше 10 то подставить 0 (04,07 и.т.д)

ComObjError(false) 
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1") 
whr.Open("POST", "https://api.vk.com/method/photos.getMessagesUploadServer?peer_id=20000000" ID "&access_token=" Token "&v=5.95", true) 
whr.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36") 
whr.SetRequestHeader("Content-Type","application/x-www-form-urlencoded")
whr.Send() 
whr.WaitForResponse()
jsontext := % whr.ResponseText
JSON = 
(LTrim Join
%jsontext% 
) 
htmldoc := ComObjCreate("htmlfile") 
Script := htmldoc.Script 
Script.execScript(" ", "JScript") 
oJSON := Script.eval("(" . JSON . ")")
upload_url := % oJSON.response.upload_url ;Получил ответ с ссылкой
uploadurl := StrReplace(upload_url, "\/", "/", count) ;Избавился от лишних слешей \

;ДАЛЕЕ ВАШ КОД
;Создание и настройка объекта для построения данных формы
form			:= ComObjGet("script:file:webFormDataBuilder.wsc")
form.method		:= "POST"
form.action		:= "%uploadurl%" ; Вводил переменную с ссылкой как % uploadurl  , но ругается на ошибку
form.enctype	:= "multipart/form-data"

;Загрузка тела файла в буффер
fileName := "3.jpeg"
;Открытие файла на чтение
file := FileOpen(fileName,"r")
if !IsObject(file)
{
    MsgBox Can't open "%FileName%" for reading.
    return
}

;Добавление тела файла в запрос
form.addFileField("file", "картинка.jpg", file.Read())
file.Close()

;Подготовка запроса к сервису
whr	:= ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.open(form.method, form.action, false)
whr.setRequestHeader("Content-Type",form.contentType)
whr.send(form.build())

;Загрузка объекта HTMLDocument
document := ComObjCreate("htmlfile")
;Установка режима совместимости
document.writeln("<meta http-equiv=""x-ua-compatible"" content=""IE=Edge""/>")
;Получение объекта JSON для разбора JSON данных
JSON := document.parentWindow.JSON
try {
    url := JSON.parse(whr.responseText).url
	ComObjCreate("WScript.Shell").Run(url)
} catch e {
	MsgBox JSON parsing failed !
}

Откуда ответ сервера вытянуть теперь?

17

Re: AHK: Отправка фото на сервер

Ладно, не обязательно загружать фото/картинку на Вк сервер, нужен любой хостинг картинок, который в ответ даст URL,
и уже URL можно подгрузить на VK.
Есть идеи что использовать?

18

Re: AHK: Отправка фото на сервер

Поиск.

19

Re: AHK: Отправка фото на сервер

Да нет, тут поиск пока бесполезен. Для начала нужно научиться знаком := правильно пользоваться. Так что справка, переменные и выражения.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

20 (изменено: wladkokopops, 2019-04-17 15:24:59)

Re: AHK: Отправка фото на сервер

ComObjError(false) 
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1") 
whr.Open("POST", "https://api.vk.com/method/photos.getMessagesUploadServer?peer_id=20000000" ID "&access_token=" Token "&v=5.95", true) 
whr.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36") 
whr.SetRequestHeader("Content-Type","application/x-www-form-urlencoded")
whr.Send() 
whr.WaitForResponse()
jsontext := % whr.ResponseText
JSON = 
(LTrim Join
%jsontext% 
) 
htmldoc := ComObjCreate("htmlfile") 
Script := htmldoc.Script 
Script.execScript(" ", "JScript") 
oJSON := Script.eval("(" . JSON . ")")
upload_url := % oJSON.response.upload_url ;Получил ответ с ссылкой
uploadurl := StrReplace(upload_url, "\/", "/", count) ;Избавился от лишних слешей \

;ДАЛЕЕ ВАШ КОД
;Создание и настройка объекта для построения данных формы
form			:= ComObjGet("script:file:webFormDataBuilder.wsc")
form.method		:= "POST"
form.action		:= StrReplace(upload_url, "\/", "/", count)
form.enctype	:= "multipart/form-data"

;Загрузка тела файла в буффер
fileName := "3.jpg"
;Открытие файла на чтение
file := FileOpen(fileName,"r")

;Добавление тела файла в запрос
form.addFileField("file", "3.jpg", file.Read())
file.Close()

;Подготовка запроса к сервису
whr	:= ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.open(form.method, form.action, false)
whr.setRequestHeader("Content-Type",form.contentType)
whr.send(form.build())

;Загрузка объекта HTMLDocument
document := ComObjCreate("htmlfile")
;Установка режима совместимости
document.writeln("<meta http-equiv=""x-ua-compatible"" content=""IE=Edge""/>")
;Получение объекта JSON для разбора JSON данных
jsontext := % whr.ResponseText
msgbox % jsontext

В ответ выдает сервер, хэш, но Photo = null
что не так? Использовал всё как сказали.

vk api :
Передайте файлы на адрес upload_url, полученный в предыдущем пункте, сформировав POST-запрос с полем photo. Это поле должно содержать изображения в формате multipart/form-data.

После успешной загрузки сервер возвращает в ответе JSON-объект с полями server, photo, hash.

21

Re: AHK: Отправка фото на сервер

wladkokopops пишет:

что не так? Использовал всё как сказали.

Ну видимо не совсем "всё как сказали". )

Вы же сами написали:

wladkokopops пишет:

.... сформировав POST-запрос с полем photo

А в коде у Вас:

wladkokopops пишет:

form.addFileField("file", "3.jpg", file.Read())

wladkokopops пишет:

Ладно, не обязательно загружать фото/картинку на Вк сервер, нужен любой хостинг картинок, который в ответ даст URL,
и уже URL можно подгрузить на VK.
Есть идеи что использовать?

Так в моём же примере, который я выложил в ZIP архиве, пример загрузки файла на https://uploadfiles.io/

Можно загрузить и на https://imgur.com/. Вот аналогичный скрипт для загрузки файла на него:

+ открыть спойлер

// Создание объекта для построения данных формы для отправки на сервер
var form = GetObject("script:file:webFormDataBuilder.wsc");
// Указание URL назначения
form.action = "https://imgur.com/upload";
// Указание метода отправки
form.method	= "POST";
// Указание типа кодирования
form.enctype = "multipart/form-data";
// Добавление поля "Filedata" c телом файла
form.addFileField("Filedata","картинка.jpg",readFile("картинка.jpg"));
// Создание объекта для отправки данных
whr = new ActiveXObject('WinHttp.WinHttpRequest.5.1');
// Установка User-Agent для отправки
whr.option(0) = 'Mozilla/5.0';
// Настройка объекта для отправки
whr.open(form.method, form.action, false);
// Установка Content-Type
whr.setRequestHeader('Content-Type',form.contentType);
whr.setRequestHeader('Referer','https://imgur.com/upload');
// Отправка подготовленных данных на сервер
var data = form.build();
// Сохранение дампа отправляемых данных для удобной отладки
saveDump(data,'post_dump.txt');
// Отправка файла на сервер
whr.send(data);

// На этом моменте отправка заканчивается и дальше идёт обработка ответа

// Проверка успешности загрузки

if(whr.status != '200') {
	WSH.Echo('Upload failed !');
} else {
	// Создание объекта для разбора JSON данных
	var JSON = (function(){
		// Загрузка объекта HTMLDocument
		var document = new ActiveXObject('htmlfile');
		// Установка режима совместимости
		document.writeln('<meta http-equiv="x-ua-compatible" content="IE=Edge"/>');
		// Подключение обработчика ошибок
		document.parentWindow.onerror = function(message, url, line, column, error){
			throw new Error(error);
		}
		return document.parentWindow.JSON;
	})();
	// Разбор JSON ответа
	try {
		var result = JSON.parse(whr.responseText);
		WSH.Echo(whr.responseText);
	} catch(e) {
		WSH.Echo('Ошибка разбора JSON данных. ' + e.description + '\r\n\r\n' + whr.responseText)
		WSH.Quit();
	}
	// Открытие URL загруженного файла
	new ActiveXObject('WScript.Shell').Run('https://imgur.com/' + result.data.hash)
}


// Внутренняя функция чтения файла
function readFile(fileName){
	var stream = new ActiveXObject("ADODB" + ".Stream");
	stream.Type = 1;
	stream.Open();
	stream.LoadFromFile(fileName);
	return stream.Read();
}

// Функция сохранения двоичного дампа отправляемых данных
function saveDump(data,fileName){
	var stream = new ActiveXObject('ADODB.Stream');
	stream.type = 1;
	stream.open();
	stream.Write(data);
	stream.SaveToFile(fileName,2);	
}
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

22 (изменено: wladkokopops, 2019-04-19 17:57:56)

Re: AHK: Отправка фото на сервер

Xameleon

Token := "TOKEN"
ID := "94" ; ид беседы в которую загрузить фото, если меньше 10 то подставить 0 (04,07 и.т.д)

ComObjError(false) 
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1") 
whr.Open("POST", "https://api.vk.com/method/photos.getMessagesUploadServer?peer_id=20000000" ID "&access_token=" Token "&v=5.95", true) 
whr.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36") 
whr.SetRequestHeader("Content-Type","application/x-www-form-urlencoded")
whr.Send() 
whr.WaitForResponse()
jsontext := % whr.ResponseText
JSON = 
(LTrim Join
%jsontext% 
) 
htmldoc := ComObjCreate("htmlfile") 
Script := htmldoc.Script 
Script.execScript(" ", "JScript") 
oJSON := Script.eval("(" . JSON . ")")
upload_url := % oJSON.response.upload_url ;Получил ответ с ссылкой
Url := StrReplace(upload_url, "\/", "/", count)
;Создание и настройка объекта для построения данных формы
form 		:= ComObjGet("script:file:webFormDataBuilder.wsc")
form.method	:= "POST"
form.action	 := Url
form.enctype := "multipart/form-data"

;Загрузка тела файла в буффер
fileName := "3.jpg"
;Открытие файла на чтение
file := FileOpen(fileName,"r")
fileout := file.Read()

;Добавление тела файла в запрос
form.addFileField("photo","3.jpg", fileout)
;Подготовка запроса к сервису
whr	:= ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.open(form.method, form.action, false)
whr.setRequestHeader("Content-Type",form.contentType)
whr.send(form.build())
;ответ ↓
jsontext := % whr.ResponseText
msgbox % jsontext

Вот , всё, ну всё как должно быть, а в ответе photo["Null"] ...
Ссылка получается правильной, запрос именно на неё,ответ приходит, но значение фото нулевое.

23

Re: AHK: Отправка фото на сервер

wladkokopops пишет:

:= %

wladkokopops, откуда вы все берёте такой синтаксис?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

24

Re: AHK: Отправка фото на сервер

wladkokopops, покажите, пожалуйста, ссылку на раздел документации, который читаете.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

25

Re: AHK: Отправка фото на сервер

vk api
https://vk.com/dev/upload_files?f=4.%20 … 0сообщение
Xameleon

26

Re: AHK: Отправка фото на сервер

Есть идеи?

27

Re: AHK: Отправка фото на сервер

wladkokopops, идеи есть всегда. ) Но для начала, чтобы попробовать выполнить Ваш код, мне надо получить access_token. Как будет время - поизучаю. Давно не ковырял API вконтакта.

Кстати, Вы каким из методов получаете access_token ?

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

28 (изменено: wladkokopops, 2019-04-19 23:43:52)

Re: AHK: Отправка фото на сервер

Беру токен отсюда
https://vkhost.github.io
беру от Katemobile,
Так же можно получить токен через прямой вход:

https://oauth.vk.com/token?grant_type=password&client_id=2274003&client_secret=hHbZxrka2uZ6jB1inYsH&username=" Login "&password=" password "

Используя такой пост, и получить в ответ токен -
Где Логин - номер телефона,
пароль - явно тот самый пароль.

Xameleon

29 (изменено: teadrinker, 2019-04-20 02:41:51)

Re: AHK: Отправка фото на сервер

Ради интереса решил попробовать. Вот так удалось загрузить фото в свой альбом:

; Выполнение запросов к API ВКонтакте: https://vk.com/dev/api_requests
; Загрузка файлов:                     https://vk.com/dev/upload_files

accessToken := "cfcc912ff7d7d2d83e4bb99f89b81ecd1b5061d5c48cde42a7eca6" ; указать свой access_token
albumId     := 102453589                                                ; album_id
filePath    := "D:\Downloads\Иконки\test.png"

JS := CreateScriptObj()
url := GetUrl(accessToken, albumId, JS)
SendFile(filePath, url, JS, server, photos_list, aid, hash)
MsgBox, % SaveFile(accessToken, server, photos_list, aid, hash)

GetUrl(accessToken, albumId, JS) {
   queryUrl := "https://api.vk.com/method/photos.getUploadServer?album_id=" . albumId . "&access_token=" . accessToken . "&v=5.95."
   whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   whr.Open("GET", queryUrl, false)
   whr.Send()
   if (whr.Status != 200)
      throw Exception(whr.responseText)
   Return JS.("JSON.parse('" . whr.ResponseText . "').response.upload_url")
}

SendFile(filePath, url, JS, ByRef server, ByRef photos_list, ByRef aid, ByRef hash) {
   CreateFormData(postData, hdr_ContentType, {file: [filePath]})
   
   whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   whr.Open("POST", url, false)
   whr.SetRequestHeader("Content-Type", hdr_ContentType)
   whr.Send(postData)
   if (whr.Status != 200)
      throw Exception(whr.responseText)
   else {
      responseText := whr.responseText
      for k, v in ["server", "photos_list", "aid", "hash"]
         %v% := StrReplace(JS.("JSON.parse('" . StrReplace(responseText, "\""", "|") . "')." . v), "|", """")
   }
}

SaveFile(accessToken, server, photos_list, aid, hash) {
   queryUrl := "https://api.vk.com/method/photos.save?server="       . server
                                                  . "&photos_list="  . URIEncode(photos_list)
                                                  . "&aid="          . aid
                                                  . "&hash="         . hash
                                                  . "&album_id="     . aid
                                                  . "&access_token=" . accessToken . "&v=5.95."
   whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
   whr.Open("GET", queryUrl, false)
   whr.Send()
   Return % whr.responseText
}

CreateScriptObj() {
   static doc
   doc := ComObjCreate("htmlfile")
   doc.write("<meta http-equiv='X-UA-Compatible' content='IE=9'>")
   Return ObjBindMethod(doc.parentWindow, "eval")
}

URIEncode(str, encoding := "UTF-8")  {
   VarSetCapacity(var, StrPut(str, encoding))
   StrPut(str, &var, encoding)

   While code := NumGet(Var, A_Index - 1, "UChar")  {
      bool := (code > 0x7F || code < 0x30 || code = 0x3D)
      UrlStr .= bool ? "%" . Format("{:02X}", code) : Chr(code)
   }
   Return UrlStr
}

CreateFormData(ByRef retData, ByRef retHeader, objParam) {
   new CreateFormData(retData, retHeader, objParam)
}

class CreateFormData
{
   __New(ByRef retData, ByRef retHeader, objParam) {
      CRLF := "`r`n", i, k, v, str, pvData
      ; Create a random Boundary
      Boundary := this.RandomBoundary()
      BoundaryLine := "------------------------------" . Boundary

      this.Len := 0 ; GMEM_ZEROINIT|GMEM_FIXED = 0x40
      this.Ptr := DllCall("GlobalAlloc", UInt, 0x40, UInt, 1, Ptr)

      ; Loop input paramters
      for k, v in objParam
      {
         if IsObject(v) {
            for i, FileName in v
            {
               str := BoundaryLine . CRLF
                    . "Content-Disposition: form-data; name=""" . k . """; filename=""" . FileName . """" . CRLF
                    . "Content-Type: " . this.MimeType(FileName) . CRLF . CRLF
               this.StrPutUTF8( str )
               this.LoadFromFile( Filename )
               this.StrPutUTF8( CRLF )
            }
         }
         else {
            str := BoundaryLine . CRLF
                 . "Content-Disposition: form-data; name=""" . k """" . CRLF . CRLF
                 . v . CRLF
            this.StrPutUTF8( str )
         }
      }
      this.StrPutUTF8( BoundaryLine . "--" . CRLF )

      ; Create a bytearray and copy data in to it.
      retData := ComObjArray(0x11, this.Len)       ; Create SAFEARRAY = VT_ARRAY|VT_UI1
      pvData  := NumGet( ComObjValue( retData ) + 8 + A_PtrSize )
      DllCall("RtlMoveMemory", Ptr, pvData, Ptr, this.Ptr, Ptr, this.Len)

      this.Ptr := DllCall("GlobalFree", Ptr, this.Ptr, Ptr)
      retHeader := "multipart/form-data; boundary=----------------------------" . Boundary
   }

   StrPutUTF8( str ) {
      ReqSz := StrPut( str, "utf-8" ) - 1
      this.Len += ReqSz                                  ; GMEM_ZEROINIT|GMEM_MOVEABLE = 0x42
      this.Ptr := DllCall("GlobalReAlloc", Ptr, this.Ptr, UInt, this.len + 1, UInt, 0x42)   
      StrPut(str, this.Ptr + this.len - ReqSz, ReqSz, "utf-8")
   }
  
   LoadFromFile( Filename ) {
      objFile := FileOpen( FileName, "r" )
      this.Len += objFile.Length                     ; GMEM_ZEROINIT|GMEM_MOVEABLE = 0x42 
      this.Ptr := DllCall("GlobalReAlloc", Ptr, this.Ptr, UInt, this.len, UInt, 0x42)
      objFile.RawRead( this.Ptr + this.Len - objFile.length, objFile.length )
      objFile.Close()
   }

   RandomBoundary() {
      str := "0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z"
      Sort, str, D| Random
      str := StrReplace(str, "|")
      Return SubStr(str, 1, 12)
   }

   MimeType(FileName) {
      n := FileOpen(FileName, "r").ReadUInt()
      Return (n        = 0x474E5089) ? "image/png"
           : (n        = 0x38464947) ? "image/gif"
           : (n&0xFFFF = 0x4D42    ) ? "image/bmp"
           : (n&0xFFFF = 0xD8FF    ) ? "image/jpeg"
           : (n&0xFFFF = 0x4949    ) ? "image/tiff"
           : (n&0xFFFF = 0x4D4D    ) ? "image/tiff"
           : "application/octet-stream"
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

30

Re: AHK: Отправка фото на сервер

Тоже решил попробовать свои силы. Получил токен, как Вы и предлагали. Загрузка на сервак прошла вообще без проблем.

Пример на JS в аттаче. Вот ответ сервера:

+ открыть спойлер

[
        {
                "photo": "c9caff4d6b:x",
                "sizes": [
                        [
                                "s",
                                854320297,
                                "2817a",
                                "zDaZi9O3wfI",
                                75,
                                75
                        ],
                        [
                                "m",
                                854320297,
                                "2817b",
                                "qMQLFw2Np34",
                                130,
                                130
                        ],
                        [
                                "x",
                                854320297,
                                "2817c",
                                "KRmDXHyMVcA",
                                225,
                                225
                        ],
                        [
                                "o",
                                854320297,
                                "2817d",
                                "gdsFzVnJo1A",
                                130,
                                130
                        ],
                        [
                                "p",
                                854320297,
                                "2817e",
                                "OE9cc9pwEIA",
                                200,
                                200
                        ],
                        [
                                "q",
                                854320297,
                                "2817f",
                                "4wThdxLDmxE",
                                225,
                                225
                        ],
                        [
                                "r",
                                854320297,
                                "28180",
                                "UfyFBGhUTZE",
                                225,
                                225
                        ]
                ],
                "latitude": 0,
                "longitude": 0,
                "kid": "8d6f44a10ece33d20957655622e49256"
        }
]

Попытался разобраться с Вашим кодом. Понял, что всё упирается в то, что AHK передаёт строку вместо байтового массива в объект webFormDataBuilder.
Честно говоря лень было разбираться с функционалом AHK. Так что вставил чтение через ADODB.Stream. При этом скрипт работает нормально.

+ открыть спойлер

Token := "..."
ID := "94" ; ид беседы в которую загрузить фото, если меньше 10 то подставить 0 (04,07 и.т.д)

;ComObjError(false) 

;Загрузка объекта HTMLDocument
document := ComObjCreate("htmlfile")
;Установка режима совместимости
document.writeln("<meta http-equiv=""x-ua-compatible"" content=""IE=Edge""/>")
;Получение объекта JSON для разбора JSON данных
JSON := document.parentWindow.JSON

whr := ComObjCreate("WinHttp.WinHttpRequest.5.1") 
whr.Option(0) := "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"

whr.Open("GET", "https://api.vk.com/method/photos.getMessagesUploadServer?peer_id=1&access_token=" . Token . "&v=5.95", false) 
whr.Send() 
data := JSON.parse(whr.responseText)

if not data.hasOwnProperty("response") {
	MsgBox Request Failed
	exit
}

upload_url := data.response.upload_url

;Создание и настройка объекта для построения данных формы
form			:= ComObjGet("script:file:webFormDataBuilder.wsc")
form.method		:= "POST"
form.action		:= upload_url
form.enctype	:= "multipart/form-data"
;Загрузка тела файла в буффер
fileName := "image.png"

;Добавление тела файла в запрос
form.addFileField("photo", fileName, readFile(fileName))
file.Close()

;Подготовка запроса к сервису
whr	:= ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.open(form.method, form.action, false)
whr.setRequestHeader("Content-Type",form.contentType)
whr.send(form.build())

MsgBox % whr.responseText

readFile(fileName){
	stream := ComObjCreate("ADODB.Stream")
	stream.Type := 1
	stream.Open()
	stream.LoadFromFile(fileName)
	return stream.Read()
}
Post's attachments

vk_upload.zip 16.13 kb, 4 downloads since 2019-04-20 

You don't have the permssions to download the attachments of this post.
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

31

Re: AHK: Отправка фото на сервер

Xameleon
Ура, работатет!
Огромное спасибо!
+ В репу однозначно.

32

Re: AHK: Отправка фото на сервер

wladkokopops, рад, что смог помочь. А Вам спасибо за информацию о получении токена и полезный ресурс. В основной документации не видел подробностей про "прямую авторизацию".

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

33

Re: AHK: Отправка фото на сервер

wladkokopops, если бы вы вбили в поиск "multipart/form-data", то увидели бы достаточно примеров как заливать файлы этим сообщением.

34

Re: AHK: Отправка фото на сервер

Malcev, да документалки хватает, но порой не хочется изобретать велосипед с нуля, если уже есть готовые. Я когда-то давно сделал себе заготовку в виде WSC компонента для упрощения подготовки данных. И с тех пор она много раз меня выручала (загрузка курсов с cbr.ru / автоматические загрузки файлов на ресурсы / автоматизация отправки форм на различных ресурсах). Для меня удобство в том, что WSC:
а) Адаптивен под разные языки. Можно не переписывать весь код, если захочется использовать в другой среде.
б) Исходный код доступен для просмотра и модификации.
в) Объект можно подгружать с внешнего ресурса.
г) Не требует регистрации в большинстве случаев.

Вчера решил попробовать закинуть вариант на гитхаб.

formDataEncoder

Пока получается коряво, так как опыта в этом нет, но надеюсь со временем научусь.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

35

Re: AHK: Отправка фото на сервер

Думаю для начинающих тут не помешает пример использования с AutoHotkey, например аналог imgur.com.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

36

Re: AHK: Отправка фото на сервер

А зачем для AHK wsc-файл нужен? Смотри мой пример.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

37

Re: AHK: Отправка фото на сервер

Xameleon пишет:

Malcev, да документалки хватает, но порой не хочется изобретать велосипед с нуля

А почему с нуля?
Есть готовая функция, которую использовал teadrinker - CreateFormData.
Если бы топикстартер удосужился поискать по форуму, то нашел бы ее с отсылкой на оф.форум, где показывается ее применение и через ADODB и без.

38

Re: AHK: Отправка фото на сервер

Malcev,

Malcev пишет:

А почему с нуля?
Есть готовая функция, которую использовал teadrinker - CreateFormData.
Если бы топикстартер удосужился поискать по форуму, то нашел бы ее с отсылкой на оф.форум, где показывается ее применение и через ADODB и без.

Согласен, но эта функция не охватывает все способы кодирования, доступные для данных формы:
Для метода GET сборка параметров в URL

+ открыть спойлер

<form action="..." method="GET">
<input name="field1">
<input name="field2">
...
</form>

Для метода POST с типами кодирования:
1) "application/x-www-form-urlencoded"
2) "text/plain"

Я постарался собрать универсальный вариант. Понимаю, что наверняка напрашивается ответ - для конкретной задачи загрузки файла(ов) на сервер, нужен только тип кодирования "multipart/form-data". Я же заложил логику на все случаи жизни так как при автоматизации работы с различными сайтами случается так, что приходится "проваливаться" по страницам с разными формами. Благодаря этому объекту можно передать в него свойства HTML формы, поля и получить подготовленные данные для WinHttpRequest / XMLHttpRequest, не задумываясь о том какой тип кодирования у формы, что резко упрощает дальнейшую разработку.

teadrinker,

teadrinker пишет:

А зачем для AHK wsc-файл нужен? Смотри мой пример.

Так я же как раз и пояснил в сообщении выше. Удобство в простоте "переброса" используемого объекта с одного языка на другой - модульность / универсальность.
Да, для AHK есть написанный код CreateFormData, но его нельзя задействовать в JS / VBS не переписав. А с WSC нет нужды в пересборке. Собственно почему мы используем COM объекты, а не переписываем их код под каждый язык ? Думаю в этом и есть некое удобство.

serzh82saratov, ну как время будет - попробую. ) Надо ещё понять востребованность данной задачи. Вот коллеги пока сомневаются. Я от части разделяю их мнение.

И конечно же, я согласен, что такое решение содержит свой ряд изъянов, но пмсм, плюсы перевешивают. По крайней мере, в тех ситуациях, где я его использовал, для меня плюсов было больше. )

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

39

Re: AHK: Отправка фото на сервер

А что тут сомневаться, больше инструментов всегда лучше, чем меньше. В небольшом проекте на скорую руку, когда не зачем лезть в дебри, или в большом, когда и так много всего, везде сгодится. Тем более если нет аналога, с полным функционалом.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64, AutoHotkey_L v1.1.30.03 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

40

Re: AHK: Отправка фото на сервер

serzh82saratov, благодарю за поддержку. Тогда подумаю над доделкой примеров на других языках.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !