Что нового

TCPInet - Альтернатива Inet* с расширенными возможностями

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
AutoIt: 3.3.6.1 - 3.3.12.0
Версия: 0.3

Категория: Интернет, Сеть

Описание:
Библиотека предназначена для скачивании файлов с расширенными возможностями (тема зарождения идеи).
Данная библиотека изначально задумывалась как альтернатива встроенным функциям Inet*, с возможностью ставить закачку на паузу.
Но в процессе её развития была также реализована поддержка callback-функции, и другие возможности.

Смежная тема: InetEx - Альтернатива Inet* с расширенными возможностями

[box title=Примечания:]
* Библиотека не поддерживает кэш и ssl (https).
* Библиотека использует Opt('TCPTimeOut', 10000) (при каждом вызове _TCPInet_GetFile или _TCPInet_GetSize)
!!! Очень важно для корректной работы функции TCP !!!
* При использовании TCPShutdown, не забудьте вызвать TCPStartup прежде чем использовать функции данной библиотеки.
* Используйте асинхронный режим (background) с осторожностью, одновременная закачка многих файлов может привести к большому потреблению памяти.
(создайте очередь и используйте _TCPInet_SetMaxBufferLen для корреляции потребления памяти).
[/box]

Примеры:
Простой:
Код:
#include 'TCPInet.au3'

Global $sPath = FileSelectFolder('Select download path', '', 1)
If @error Then Exit

HotKeySet('^+a', '_Abort')

Global $sFile1 = 'http://creator-lab.ucoz.ru/Testing_Zone/Opera_Dll.zip'
Global $sFile2 = 'http://svn2.assembla.com/svn/anthraxinteractive/encrpytion/emdll/au3src/src/AutoIt.cpp'

$hInet1 = _TCPInet_GetFile($sFile1, $sPath, True, $TCPINET_DOWNLOADBACKGROUND, '_My_TCPInet_Callback')
$hInet2 = _TCPInet_GetFile($sFile2, $sPath, True, $TCPINET_DOWNLOADBACKGROUND, '_My_TCPInet_Callback')

While _TCPInet_GetInfo() > 0
	Sleep(1000)
WEnd

_Abort()

Func _Abort()
	_TCPInet_Close($hInet1)
	_TCPInet_Close($hInet2)
EndFunc

Func _My_TCPInet_Callback($hInet, $vData)
	Local $aInfo = _TCPInet_GetInfo($hInet, -1)
	
	If @error Or $aInfo[$TCPINET_DOWNLOADCOMPLETE] Then
		Return $TCPINET_CB_CONTINUE
	EndIf
	
	Local $sProgress = (Floor($aInfo[$TCPINET_DOWNLOADREAD] / $aInfo[$TCPINET_DOWNLOADSIZE] * 1000) / 10) & '%'
	Local $sFileName = StringRegExpReplace($aInfo[$TCPINET_DOWNLOADFILE], '^.*\\', '')
	
	ConsoleWrite('Downloading [' & $sFileName & ']: ' & $sProgress & @LF)
EndFunc


Продвинуты (от Yashied):
Код:
#NoTrayIcon

#include <EditConstants.au3>
#include <ListViewConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GUIListView.au3>
#include <Misc.au3>
#include <WinAPI.au3>
#include 'TCPInet.au3'

Opt('GUICloseOnESC', 0)
Opt('MustDeclareVars', 1)

Global $hForm, $hLV, $Button[3], $ID, $Job, $Item = -1, $Int = False

$hForm = GUICreate('TCPInet UDF Example', 760, 440)
GUICtrlCreateListView('', 0, 0, 760, 398, BitOR($LVS_DEFAULT, $LVS_NOSORTHEADER), BitOR($WS_EX_TRANSPARENT, $WS_EX_WINDOWEDGE))
GUICtrlSetFont(-1, 8.5, 400, 0, 'Tahoma')
$hLV = GUICtrlGetHandle(-1)
_GUICtrlListView_SetExtendedListViewStyle($hLV, BitOR($LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $LVS_EX_INFOTIP))
_GUICtrlListView_AddColumn($hLV, 'URL', 304)
_GUICtrlListView_AddColumn($hLV, 'Localtion', 204)
_GUICtrlListView_AddColumn($hLV, 'Progress', 55, 1)
_GUICtrlListView_AddColumn($hLV, 'Status', 90)
_GUICtrlListView_AddColumn($hLV, 'Error', 90)
GUICtrlCreateLabel('', 0, 398, 763, 2, $SS_ETCHEDHORZ)
$Button[0] = GUICtrlCreateButton('Download...', 5, 405, 248, 30)
GUICtrlSetState(-1, $GUI_FOCUS)
$Button[1] = GUICtrlCreateButton('Pause', 257, 405, 247, 30)
GUICtrlSetState(-1, $GUI_DISABLE)
$Button[2] = GUICtrlCreateButton('Remove', 508, 405, 247, 30)
GUICtrlSetState(-1, $GUI_DISABLE)
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

While 1
	Switch GUIGetMsg()
		Case 0
			ContinueLoop
		Case $GUI_EVENT_CLOSE
			ExitLoop
		Case $Button[0] ; "Download..."
			$Job = _SHDownloadDlg($hForm)
			
			If IsArray($Job) Then
				$ID = _LV_Add($Job[0])
				
				If Not _TCPInet_GetFile($Job[0], $Job[1], 1, $TCPINET_DOWNLOADBACKGROUND, '_Inet_Progress', $ID) Then
					MsgBox(16, 'Error', 'Unable to start download.', 0, $hForm)
					_LV_Remove()
				EndIf
			EndIf
		Case $Button[1] ; "Pause/Resume"
			_BN_Pause()
		Case $Button[2] ; "Remove"
			_BN_Remove()
			_LV_Remove()
	EndSwitch
WEnd

Func _BN_Pause()
	Local $ID = _GUICtrlListView_GetItemParam($hLV, $Item)
	
	Switch $ID
		Case 1 To 65535
			_TCPInet_Pause($ID, Not _TCPInet_GetInfo($ID, $TCPINET_DOWNLOADPAUSED))
			_BN_Set($ID)
	EndSwitch
EndFunc ;==>_BN_Pause

Func _BN_Remove()
	Local $ID = _GUICtrlListView_GetItemParam($hLV, $Item)
	
	Switch $ID
		Case 1 To 65535
			_TCPInet_Close($ID)
	EndSwitch
EndFunc ;==>_BN_Remove

Func _BN_Set($ID)
	Local $Set[2], $Info = Default
	
	Switch $ID
		Case 1 To 65535
			$Info = _TCPInet_GetInfo($ID)
			If $Info[2] Then
				$Set[0] = 0
			Else
				$Set[0] = 1
			EndIf
			$Set[1] = 1
		Case Else
			$Set[0] = 0
			$Set[1] = 0
	EndSwitch
	
	For $i = 0 To 1
		If $Set[$i] Then
			If BitAND(GUICtrlGetState($Button[$i + 1]), $GUI_DISABLE) Then
				GUICtrlSetState($Button[$i + 1], $GUI_ENABLE)
			EndIf
			
			Switch $i
				Case 0
					If (Not IsArray($Info)) Or (Not $Info[5]) Then
						If GUICtrlRead($Button[$i + 1]) = 'Resume' Then
							GUICtrlSetData($Button[1], 'Pause')
						EndIf
					Else
						If GUICtrlRead($Button[$i + 1]) = 'Pause' Then
							GUICtrlSetData($Button[1], 'Resume')
						EndIf
					EndIf
			EndSwitch
		Else
			If BitAND(GUICtrlGetState($Button[$i + 1]), $GUI_ENABLE) Then
				GUICtrlSetState($Button[$i + 1], $GUI_DISABLE)
			EndIf
			
			Switch $i
				Case 0
					If GUICtrlRead($Button[$i + 1]) = 'Resume' Then
						GUICtrlSetData($Button[1], 'Pause')
					EndIf
			EndSwitch
		EndIf
	Next
	
	If Not _GUICtrlListView_GetItemCount($hLV) Then
		GUICtrlSetState($Button[0], $GUI_FOCUS)
	EndIf
EndFunc ;==>_BN_Set

Func _GetID()
	Local Static $ID = 65535
	
	If $ID = 2147483647 Then
		$ID = 65536
	Else
		$ID += 1
	EndIf
	
	Return $ID
EndFunc ;==>_GetID

Func _LV_Add($sUrl)
	Local $ID = _GetID()
	
	$Int += 1
	
	_GUICtrlListView_BeginUpdate($hLV)
	$Item = _GUICtrlListView_AddItem($hLV, $sUrl, -1, $ID)
	_GUICtrlListView_SetItemSelected($hLV, $Item, 1, 1)
	_GUICtrlListView_EnsureVisible($hLV, $Item)
	_GUICtrlListView_EndUpdate($hLV)
	_WinAPI_SetFocus($hLV)
	_BN_Set($ID)
	
	$Int -= 1
	
	Return $ID
EndFunc ;==>_LV_Add

Func _LV_Remove()
	Local $ID = 0
	
	$Int += 1
	
	_GUICtrlListView_BeginUpdate($hLV)
	_GUICtrlListView_DeleteItem($hLV, $Item)
	
	If $Item > _GUICtrlListView_GetItemCount($hLV) - 1 Then
		$Item -= 1
	EndIf
	
	If $Item > -1 Then
		$ID = _GUICtrlListView_GetItemParam($hLV, $Item)
		_GUICtrlListView_SetItemSelected($hLV, $Item, 1, 1)
		_GUICtrlListView_EnsureVisible($hLV, $Item)
	EndIf
	
	_GUICtrlListView_EndUpdate($hLV)
	_BN_Set($ID)
	
	$Int -= 1
EndFunc ;==>_LV_Remove

Func _SHDownloadDlg($hParent)
	Local $hDlg, $Button, $Input, $Msg
	Local $Job[2] = ['', '']
	
	Opt('GUICloseOnESC', 1)
	
	If $hParent Then
		GUISetState(@SW_DISABLE, $hParent)
	EndIf
	
	$hDlg = GUICreate('Add Location', 340, 97, -1, -1, BitOR($WS_CAPTION, $WS_POPUP, 0, $WS_SYSMENU), $WS_EX_DLGMODALFRAME, $hParent)
	GUICtrlCreateLabel('URL:', 14, 28, 27, 14)
	$Input = GUICtrlCreateInput('', 42, 25, 282, 19, BitOR($ES_AUTOHSCROLL, $ES_LEFT, $ES_MULTILINE))
	GUICtrlSetState(-1, $GUI_FOCUS)
	$Button = GUICtrlCreateButton('OK', 131, 62, 78, 25)
	GUICtrlSetState(-1, $GUI_DEFBUTTON)
	GUISetState(@SW_SHOW, $hDlg)
	
	While 1
		$Msg = GUIGetMsg()
		Switch $Msg
			Case 0
				ContinueLoop
			Case $GUI_EVENT_CLOSE
				ExitLoop
			Case $Button
				$Job[0] = StringStripWS(GUICtrlRead($Input), 8)
				
				If StringRegExp($Job[0], '(?i)^http://[^/]+/.+') Then
					ExitLoop
				EndIf
		EndSwitch
	WEnd
	
	If $hParent Then
		GUISetState(@SW_ENABLE, $hParent)
	EndIf
	
	GUIDelete($hDlg)
	Opt('GUICloseOnESC', 0)
	
	If $Job[0] Then
		$Job[1] = FileSelectFolder('', '::{20D04FE0-3AEA-1069-A2D8-08002B30309D}', 0, @WorkingDir, $hParent)
		
		If $Job[1] Then
			FileChangeDir($Job[1])
			$Job[1] = StringRegExpReplace($Job[1], '\\+$', '')
			Return $Job
		EndIf
	EndIf
	
	Return 0
EndFunc ;==>_SHDownloadDlg

Func _Inet_Progress($hInet, $iID)
	Local $Info = _TCPInet_GetInfo($hInet)
	Local $ID, $Index = -1
	Local $Data[3]
	
	For $i = 0 To _GUICtrlListView_GetItemCount($hLV) - 1
		$ID = _GUICtrlListView_GetItemParam($hLV, $i)
		
		If ($ID = $hInet) Or ($ID = $iID) Then
			$Index = $i
			
			If $ID > 65535 Then
				_GUICtrlListView_SetItemText($hLV, $Index, $Info[6], 1)
				_GUICtrlListView_SetItemParam($hLV, $Index, $hInet)
			EndIf
			
			ExitLoop
		EndIf
	Next
	
	If $Index = -1 Then
		Return $TCPINET_CB_CONTINUE
	EndIf
	
	If $Info[1] Then
		$Data[0] = Floor($Info[0] / $Info[1] * 100) & '%'
	Else
		If $Info[2] Then
			$Data[0] = '100%'
		Else
			$Data[0] = '?'
		EndIf
	EndIf
	
	If $Info[2] Then
		If $Info[3] Then
			$Data[1] = 'Complete'
			$Data[2] = '0'
		Else
			$Data[1] = 'Error'
			$Data[2] = String($Info[4])
		EndIf
	Else
		If $Info[5] Then
			$Data[1] = 'Pause'
		Else
			$Data[1] = 'Downloading'
		EndIf
	EndIf
	
	_GUICtrlListView_BeginUpdate($hLV)
	$Info = _GUICtrlListView_GetItemTextArray($hLV, $Index)
	
	For $i = 0 To 2
		If $Data[$i] <> $Info[$i + 2] Then
			_GUICtrlListView_SetItemText($hLV, $Index, $Data[$i], $i + 2)
		EndIf
	Next
	
	_GUICtrlListView_RedrawItems($hLV, $Index, $Index)
	_GUICtrlListView_EndUpdate($hLV)
	
	If $Index = $Item Then
		_BN_Set($ID)
	EndIf
	
	Return $TCPINET_CB_CONTINUE
EndFunc ;==>_Inet_Progress

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
	Local Static $Flag = False
	
	Local $uint = ''
	If @AutoItX64 Then $uint = 'uint;'
	
;~ 	Local $tNMLV = DllStructCreate($tagNMLISTVIEW , $lParam)
	Local $tNMLV = DllStructCreate('hwnd hWndFrom;uint_ptr IDFrom;int Code;' & $uint & 'int Item;int SubItem;uint NewState;uint OldState;uint Changed;long ActionX;long ActionY;lparam Param', $lParam)
	Local $hTarget = DllStructGetData($tNMLV, 'hWndFrom')
	Local $Code = DllStructGetData($tNMLV, 'Code')
	Local $Path
	
	Switch $hTarget
		Case $hLV
			Switch $Code
				Case $LVN_BEGINDRAG
					Return 0
				Case $LVN_ITEMACTIVATE
					If $Item > -1 Then
						$Path = _GUICtrlListView_GetItemText($hTarget, $Item, 1)
						
						If FileExists($Path) Then
							ShellExecute('explorer.exe', '/select,' & $Path)
						EndIf
					EndIf
				Case $LVN_ITEMCHANGED
					If $Int Then
						Return $GUI_RUNDEFMSG
					EndIf
					
					If (BitAND(DllStructGetData($tNMLV, 'Changed'), $LVIF_STATE)) And (BitXOR(DllStructGetData($tNMLV, 'NewState'), DllStructGetData($tNMLV, 'OldState'))) Then
						If BitAND(DllStructGetData($tNMLV, 'NewState'), $LVIS_SELECTED) Then
							_BN_Set(DllStructGetData($tNMLV, 'Param'))
							$Item = DllStructGetData($tNMLV, 'Item')
							$Flag = 0
						Else
							If BitAND(DllStructGetData($tNMLV, 'OldState'), $LVIS_FOCUSED) Then
								$Flag = 1
							Else
								If Not $Flag Then
									_BN_Set(0)
									$Item = -1
								EndIf
								
								$Flag = 0
							EndIf
						EndIf
					EndIf
				Case $NM_CUSTOMDRAW
;~ 					Local $tNMLVCD = DllStructCreate($tagNMLVCUSTOMDRAW , $lParam)
					Local $tNMLVCD = DllStructCreate('hwnd hWndFrom;uint_ptr IDFrom;int Code;' & $uint & 'dword DrawStage;hwnd hDC;long Left;long Top;long Right;long Bottom;dword_ptr ItemSpec;uint ItemState;lparam ItemParam;dword clrText;dword clrTextBk;int SubItem;dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartId;int StateId;long TextLeft;long TextTop;long TextRight;long TextBottom;uint Align', $lParam)
					Local $Stage = DllStructGetData($tNMLVCD, 'DrawStage')
					Local $ID = DllStructGetData($tNMLVCD, 'ItemParam')
					Local $Info
					
					Switch $Stage
						Case $CDDS_ITEMPREPAINT
							Return $CDRF_NOTIFYSUBITEMDRAW
						Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM)
							Switch $ID
								Case 1 To 65535
									$Info = _TCPInet_GetInfo($ID)
									
									If $Info[2] Then
										If $Info[3] Then
											DllStructSetData($tNMLVCD, 'clrTextBk', 0x80FF80)
										Else
											DllStructSetData($tNMLVCD, 'clrTextBk', 0xAAAAFF)
										EndIf
									Else
										If $Info[5] Then
											DllStructSetData($tNMLVCD, 'clrTextBk', 0x99FFFF)
										EndIf
									EndIf
							EndSwitch
							
							Return $CDRF_DODEFAULT
					EndSwitch
				Case $NM_CLICK, $NM_DBLCLK, $NM_RCLICK, $NM_RDBLCLK
					Return 0
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc

Файл: TCPInet.zip

Снимок:


История версий:
v0.3
* Исправлена проблема с FileOpen/Write, теперь используется WinAPI для записи в файл.
* Исправлена проблема с ошибкой №3 (некоторые хосты не позволяют пустой Referer -> $sReferer = '').
* Изменены возвращаемые значения для функции _TCPInet_GetFile и _TCPInet_GetInfo (см. описание к функциям).
* TCPTimeOut увеличено до 10000.

v0.2
* Теперь имеется возможность скачивать в память (см. описание к _TCPInet_GetFile).
* Небольшие поправки.
* Изменены примеры.

v0.1
* Первая публичная версия

Источник: autoit-script.ru
Автор(ы): G.Sandler (CreatoR)
Спасибо: Yashied за существенный вклад в развитие библиотеки и за пример
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
в одном из примеров Ex Advanced+.au3 используется функция
Код:
_Iif

в версии языка 3.3.12.0 ее нет
предыдущая строка в примере отмечена комментарием
Код:
Local $tNMLV = DllStructCreate($tagNMLISTVIEW , $lParam)

я так понял, ее нужно использовать для последней версии языка.
сделал изменение, но не понял как работать с примером
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
оказалось не со всеми ссылками работает.
https://www.autoitscript.com/files/autoit3/autoit-v3-setup.exe
с этой ссылкой не работает ни один пример
 

alex33

Скриптер
Сообщения
1,457
Репутация
186

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
не обратил внимание. ну..что сказать..жаль :smile:
значит эта библиотека не совсем альтернатива функциям Inet*
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Ну, прикрутить SSL и будет хорошая альтернатива, тем более мне нравится, что есть асинхронный режим с одновременным скачиванием.
Вопрос. _TCPInet_GetFile сохраняет в файл? или можно указать переменную/элемент массива?
Если в файл, то нельзя ли сделать так, что бы сохраняла в переменную? Очень часто требуется копировать одновременно много файлов, в основном html, а так как InetGet сохраняет только в файл, то не очень удобно.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Ребята, цитирую...
[?]
Данная библиотека изначально задумывалась как альтернатива встроенным функциям Inet*, с возможностью ставить закачку на паузу.

inververs [?]
сделать так, что бы сохраняла в переменную
Думаю можно будет сделать функцию _TCPInet_Read.

Очень часто требуется копировать одновременно много файлов, в основном html, а так как InetGet сохраняет только в файл, то не очень удобно
Ну на данный момент есть InetRead, который можно запускать в отдельном процессе.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Обновление:

v0.2
* Теперь имеется возможность скачивать в память (см. описание к _TCPInet_GetFile).
* Небольшие поправки.
* Изменены примеры.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Обновил архив, в примерах была ошибка (пропущен параметр $fOverwrite).
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Обновление...

v0.3
* Исправлена проблема с FileOpen/Write, теперь используется WinAPI для записи в файл.
* Исправлена проблема с ошибкой №3 (некоторые хосты не позволяют пустой Referer -> $sReferer = '').
* Изменены возвращаемые значения для функции _TCPInet_GetFile и _TCPInet_GetInfo (см. описание к функциям).
* TCPTimeOut увеличено до 10000.

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