Что нового

Загрузка файлов в Интернет. Пример для rghost.ru

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
AutoIt: 3.3.8.1
Версия: 1.0

Категория: Интернет, Автоматизация, Загрузка файлов

Ключевые слова: WinHTTP, Upload, rghost.ru, Закачать, multipart/form-data, boundary

Описание: Функция для загрузки файла на файлохранилище rghost.ru.
В функции показан принцип формирование запроса формы multipart/form-data для отправки файлов на сервер.
Для работы понадобится библиотека WinHTTP. Взять ее можно здесь
Все важные строчки прокомментированы, что бы легче было разбираться.


Код/Пример для официальной версии:
Код:
#include "WinHTTP.au3"
Local $sFileOpenDialog = FileOpenDialog('Выбрать файл для загрузки', @DesktopDir, 'Все файлы (*.*)', 1)
If @error Then
	Exit MsgBox(16, "Отмена", "Файл не выбран. Конец.")
EndIf

Local $URL = FileUpload_Rghost($sFileOpenDialog)
If @error Then
	MsgBox(16, "Ошибка", "Файл не загружен. Ошибка: " & @error & ":" & @extended)
Else
	MsgBox(64, "Ок", "Файл загружен." & @CRLF & "URL = " & $URL)
EndIf
Exit


Код/Пример для бета версии:
Код:
#include "WinHTTP.au3"
#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
Local $sFileOpenDialog = FileOpenDialog('Выбрать файл для загрузки', @DesktopDir, 'Все файлы (*.*)', $FD_FILEMUSTEXIST)
If @error Then
	Exit MsgBox($MB_OK + $MB_ICONERROR, "Отмена", "Файл не выбран. Конец.") 
EndIf

Local $URL = FileUpload_Rghost($sFileOpenDialog)
If @error Then
	MsgBox($MB_OK + $MB_ICONERROR, "Ошибка", "Файл не загружен. Ошибка: " & @error & ":" & @extended)
Else
	MsgBox($MB_OK + $MB_ICONINFORMATION, "Ок", "Файл загружен." & @CRLF & "URL = " & $URL)
EndIf
Exit


Сама функция FileUpload_Rghost:
Код:
Func FileUpload_Rghost($sFilePath)
	#cs
		Функция загружает файл на хостинг http://rghost.ru/
		Файл хранится с параметрами по умолчанию

		В случае успеха возвращает URL файла.

		В случае ошибок устанавливает @error:
		1 - Файл не существует
		2 - Не удалось создать подключение к rghost.ru
		3 - Не удалось отправить данные на rghost.ru
		4 - Не удалось получить тэги input из кода страницы сайта rghost.ru
		5 - Не удалось создать подключение к kaon.rghost.ru
		6 - Не удалось отправить данные на kaon.rghost.ru
		7 - Не удалось получить правильный URL из ответа
		@extended - Устанавливает причину ошибок.
	#ce

	Local $hOpen, $hConnect
	Local $error, $extended, $return
	Do
		If Not FileExists($sFilePath) Then ;Файл не существует
			$error = 1
			ExitLoop
		EndIf

		$hOpen = _WinHttpOpen('Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0') ;Строка useragent

		;Установим тайм-ауты ожиданий. Если большие файлы не загружаются, то увеличивайте значения.
;~ 		;Сейчас установлено 3 минуты на отправку запроса и 2 минуты на ожидание ответа.
		_WinHttpSetTimeouts($hOpen, 0, 60 * 1000, 3 * 60 * 1000, 2 * 60 * 1000)

		$hConnect = _WinHttpConnect($hOpen, 'rghost.ru') ;Подключаемся к rghost.ru
		If @error Then
			$extended = @error
			$error = 2
			ExitLoop
		EndIf
		Local $vData = _WinHttpSimpleRequest($hConnect, 'GET', '/', Default, Default, Default, Default, 1) ;Получаем главную страницу, кодировка UTF-8
		If @error Then
			$extended = @error
			$error = 3
			ExitLoop
		EndIf
		_WinHttpCloseHandle($hConnect)

		;Для отправки формы нам нужно собрать значения следующих полей:
		Local $aNames[3][2] = [['utf8'],['authenticity_token'],['commit']]

		$vData = StringRegExpReplace($vData, "(?s)<!--.*?-->", "") ; Удаление комментариев
		$vData = StringRegExpReplace($vData, "(?s)<!\[CDATA\[.*?\]\]>", "") ; Удаление CDATA

		;Все эти поля - это тэги input, поэтому собираем все тэги input со страницы
		Local $_Temp, $aTags = StringRegExp($vData, '<\s*' & 'input' & ' [^>]+>', 3)
		If Not IsArray($aTags) Then
			$error = 4
			$extended = 0
			ExitLoop
		EndIf

		;Все тэги собраны, ищем среди них нужные нам
		For $iData = 0 To UBound($aNames) - 1
			For $Tag In $aTags
				StringRegExp($Tag, 'name' & '\s*=\s*(?:"|''|)(\Q' & $aNames[$iData][0] & '\E)(?:"|''| |\Z)', 1)
				If @error Then ContinueLoop
				$_Temp = StringRegExp($Tag, 'value\s*=\s*(?:"|''|)(.*?)(?:"|''| |\Z)', 1) ;Тэг найден, ищем чему равен value
				If @error Then ContinueLoop
				$aNames[$iData][1] = $_Temp[0]
				ExitLoop
			Next
		Next

		;Подготавливаем заголовки и тело запроса. Форма: multipart/form-data
		Local $sBoundary = StringFormat("%s%.5f", "----WinInetBoundaryLine_", Random(10000, 99999))
		Local $sHead = ''
		$sHead &= 'X-Requested-With: XMLHttpRequest' & @CRLF
		$sHead &= 'X-Awesome-Uploader: is awesome' & @CRLF
		$sHead &= 'Referer: http://rghost.ru/' & @CRLF
		$sHead &= 'Origin: http://rghost.ru' & @CRLF
		$sHead &= 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' & @CRLF
		$sHead &= 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3' & @CRLF
		$sHead &= 'Host: kaon.rghost.ru' & @CRLF
		$sHead &= 'Content-Type: multipart/form-data; boundary=' & $sBoundary & @CRLF

		;Добавляем в запрос собранные пары name=value
		Local $sData = '--' & $sBoundary & @CRLF
		For $iNames = 0 To UBound($aNames) - 1
			$sData &= 'Content-Disposition:form-data; name="' & $aNames[$iNames][0] & '"' & @CRLF & @CRLF & $aNames[$iNames][1] & @CRLF & '--' & $sBoundary & @CRLF
		Next

		;Добавляем в конец содержимое файла отправки
		;Т.к. в имени файла может быть кириллица, то перекодируем имя в URLEncode
		$sData &= 'Content-Disposition:form-data; name="file"; filename="' & __WinHttpURLEncode(StringRegExpReplace($sFilePath, ".*\\", "")) & '"' & @CRLF ;
		$sData &= 'Content-Type: ' & __WinHttpMIMEType($sFilePath) & @CRLF & @CRLF & FileRead($sFilePath) & @CRLF

		;Все содержимое добавлено, закрываем запрос
		$sData &= '--' & $sBoundary & "--" & @CRLF

		;подключаемся к другому домену, запрос на сохранение уходит туда
		$hConnect = _WinHttpConnect($hOpen, 'kaon.rghost.ru')
		If @error Then
			$extended = @error
			$error = 5
			ExitLoop
		EndIf

		; Отправляем запрос методом POST по пути kaon.rghost.ru/files. Передаем заголовки и тело.
		$vData = _WinHttpSimpleRequest($hConnect, 'POST', '/files', Default, $sData, $sHead, Default, 1)
		If @error Then
			$extended = @error
			$error = 6
			ExitLoop
		EndIf

		;Закрываем хэндлы
		_WinHttpCloseHandle($hConnect)
		_WinHttpCloseHandle($hOpen)

		;Разбираем ответ регуляркой. Достаем URL файла
		Local $_URL = StringRegExp($vData, 'top\.location\.href\s*=\s*(?:"|''|)(.*?)(?:"|''| |\Z)', 1)
		If @error Then
			$extended = @error
			$error = 7
			ExitLoop
		EndIf

		;Ответ разобран. Помещаем его в $return
		$error = 0
		$extended = 0
		$return = $_URL[0]
	Until 1

	If $hConnect Then _WinHttpCloseHandle($hConnect)
	If $hOpen Then _WinHttpCloseHandle($hOpen)

	;Конец функции
	Return SetError($error, $extended, $return)
EndFunc   ;==>FileUpload_Rghost


История версий:
1.1 Первая версия

Источник: autoit-script.ru
Автор(ы): inververs
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Через Internet Explorer.

Что бы не нажимать на кнопку "Обзор" , не отлавливать окно и не вставлять имя файла, то имитируем отправку формы, попутно собираем все поля имеющие имя.

Код:
Func _IEFormSendFile(ByRef $oIE, ByRef $oForm, $sFilePath)
	Local $sBoundary = StringFormat("%s%.5f", "----IEBoundaryLine_", Random(10000, 99999))
	Local $sHead = ''
	$sHead &= 'Content-Type: multipart/form-data; boundary=' & $sBoundary & @CRLF
	Local $sFileData = ''
	Local $sData = '--' & $sBoundary & @CRLF
	Local $oFormElements = _IEFormElementGetCollection($oForm)
	If IsObj($oFormElements) Then
		For $oElement In $oFormElements
			If Not IsObj($oElement) Then ContinueLoop
			If Not $oElement.name Then ContinueLoop
			If $oElement.type == 'file' Then
				$sFileData &= 'Content-Disposition: form-data; name="' & $oElement.name & '"; filename="' & __WinHttpURLEncode(StringRegExpReplace($sFilePath, ".*\\", "")) & '"' & @CRLF ;
				$sFileData &= 'Content-Type: ' & __WinHttpMIMEType($sFilePath) & @CRLF & @CRLF & FileRead($sFilePath) & @CRLF
			Else
				$sData &= 'Content-Disposition:form-data; name="' & $oElement.name & '"' & @CRLF & @CRLF & $oElement.value & @CRLF & '--' & $sBoundary & @CRLF
			EndIf
		Next
	EndIf
	$sData &= $sFileData
	$sData &= '--' & $sBoundary & "--" & @CRLF
	__IENavigate($oIE, $oForm.action, 1, 0, '', StringToBinary($sData), $sHead)
EndFunc   ;==>_IEFormSendFile


Простой пример:
Код:
#include "WinHTTP.au3"
#include <IE.au3>
Local $oForm = _IEFormGetObjByName($oIE, 'NameOfForm') ;Нужно передать объект формы
Local $sFilePath = @ScriptDir & '\send.jpg' ;путь к файлу
_IEFormSendFile($oIE, $oForm, $sFilePath)
 
Верх