Тема: AHK: FTP Работа с фтп
Как узнать размер файла лежащего на фтп, не скачивая его.
Мне нужно удостовериться, что файл залит целиком.
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Как узнать размер файла лежащего на фтп, не скачивая его.
Мне нужно удостовериться, что файл залит целиком.
Вот здесь посмотри. Только нужно перевести на "современный" AHK.
Вот так работает.
Но 4 вопроса.
1) Если прервался во время заливки интернет, то после загрузки файла на фтп, скрипт возвращает правильный размер, но потом почему-то на фтп новый файл стирается, а появляется старый, который прервался.
Как такое избежать?
Вариант стирать каждый раз в начале скрипта файл по маске .pureftpd-upload как-то не очень.
2) Возможно ли при прерывании интернета продолжить загружать файл, а не начинать заново?
3) Если прекратится инет или на фтп не будет места во время исполнения
fileTransfer := FtpPutFile(localFile, remoteFile)
Как разделить эти 2 возможных случая, типа 2 разных msgbox?
4) Легко ли вставить процентуальный счетчик заливки и оставшегося на заливку времени?
FtpHost = ftp.***
FtpPort = 21
FtpUsername = ***
FtpPassword = ***
localFile = E:\***
remoteFile = ***
uploadFile:
FtpConnection := FtpOpen(FtpHost, FtpPort, FtpUsername, FtpPassword)
If (FtpConnection != 1)
{
msgbox, Пропал инет
GoTo, uploadFile
}
fileTransfer := FtpPutFile(localFile, remoteFile)
If (fileTransfer != 1)
{
msgbox, Нету места
GoTo, uploadFile
}
msgbox, upload complete
Size := FtpGetFileSize(remoteFile)
msgbox, % Size
FtpClose()
Return
;;;; THE BELOW CODE IS FROM THE LIBRARY - just to make this a runnable example
/*
http://msdn.microsoft.com/library/en-us/wininet/wininet/ftp_sessions.asp
http://msdn.microsoft.com/library/en-us/wininet/wininet/internetopen.asp
http://msdn.microsoft.com/library/en-us/wininet/wininet/internetconnect.asp
*/
FtpCreateDirectory(DirName) {
global ic_hInternet
r := DllCall("wininet\FtpCreateDirectory", "Ptr", ic_hInternet, "str", DirName)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}
FtpRemoveDirectory(DirName) {
global ic_hInternet
r := DllCall("wininet\FtpRemoveDirectory", "Ptr", ic_hInternet, "str", DirName)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}
FtpSetCurrentDirectory(DirName) {
global ic_hInternet
r := DllCall("wininet\FtpSetCurrentDirectory", "Ptr", ic_hInternet, "str", DirName)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}
FtpPutFile(LocalFile, NewRemoteFile="", Flags=0) {
;Flags:
;FTP_TRANSFER_TYPE_UNKNOWN = 0 (Defaults to FTP_TRANSFER_TYPE_BINARY)
;FTP_TRANSFER_TYPE_ASCII = 1
;FTP_TRANSFER_TYPE_BINARY = 2
If NewRemoteFile=
NewRemoteFile := LocalFile
global ic_hInternet
r := DllCall("wininet\FtpPutFile"
, "Ptr", ic_hInternet
, "str", LocalFile
, "str", NewRemoteFile
, "uint", Flags
, "uint", 0) ;dwContext
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}
FtpGetFile(RemoteFile, NewFile="", Flags=0) {
;Flags:
;FTP_TRANSFER_TYPE_UNKNOWN = 0 (Defaults to FTP_TRANSFER_TYPE_BINARY)
;FTP_TRANSFER_TYPE_ASCII = 1
;FTP_TRANSFER_TYPE_BINARY = 2
If NewFile=
NewFile := RemoteFile
global ic_hInternet
r := DllCall("wininet\FtpGetFile"
, "Ptr", ic_hInternet
, "str", RemoteFile
, "str", NewFile
, "int", 1 ;do not overwrite existing files
, "uint", 0 ;dwFlagsAndAttributes
, "uint", Flags
, "uint", 0) ;dwContext
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}
FtpGetFileSize(FileName, Flags=0) {
;Flags:
;FTP_TRANSFER_TYPE_UNKNOWN = 0 (Defaults to FTP_TRANSFER_TYPE_BINARY)
;FTP_TRANSFER_TYPE_ASCII = 1
;FTP_TRANSFER_TYPE_BINARY = 2
global ic_hInternet
fof_hInternet := DllCall("wininet\FtpOpenFile"
, "Ptr", ic_hInternet
, "str", FileName
, "uint", 0x80000000 ;dwAccess: GENERIC_READ
, "uint", Flags
, "uint", 0, "Ptr") ;dwContext
If (ErrorLevel != 0 or fof_hInternet = 0)
return -1
FileSize := DllCall("wininet\FtpGetFileSize", "Ptr", fof_hInternet, "uint", 0)
DllCall("wininet\InternetCloseHandle", "Ptr", fof_hInternet)
return, FileSize
}
FtpDeleteFile(FileName) {
global ic_hInternet
r := DllCall("wininet\FtpDeleteFile", "Ptr", ic_hInternet, "str", FileName)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}
FtpRenameFile(Existing, New) {
global ic_hInternet
r := DllCall("wininet\FtpRenameFile", "Ptr", ic_hInternet, "str", Existing, "str", New)
If (ErrorLevel != 0 or r = 0)
return 0
else
return 1
}
FtpOpen(Server, Port=21, Username=0, Password=0 ,Proxy="", ProxyBypass="") {
IfEqual, Username, 0, SetEnv, Username, anonymous
IfEqual, Password, 0, SetEnv, Password, anonymous
If (Proxy != "")
AccessType=3
Else
AccessType=1
;#define INTERNET_OPEN_TYPE_PRECONFIG 0 // use registry configuration
;#define INTERNET_OPEN_TYPE_DIRECT 1 // direct to net
;#define INTERNET_OPEN_TYPE_PROXY 3 // via named proxy
;#define INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY 4 // prevent using java/script/INS
global ic_hInternet, io_hInternet, hModule
hModule := DllCall("LoadLibrary", "str", "wininet.dll", "Ptr")
io_hInternet := DllCall("wininet\InternetOpen"
, "str", A_ScriptName ;lpszAgent
, "UInt", AccessType
, "str", Proxy
, "str", ProxyBypass
, "UInt", 0, "Ptr") ;dwFlags
If (ErrorLevel != 0 or io_hInternet = 0) {
FtpClose()
return 0
}
ic_hInternet := DllCall("wininet\InternetConnect"
, "Ptr", io_hInternet
, "str", Server
, "uint", Port
, "str", Username
, "str", Password
, "uint" , 1 ;dwService (INTERNET_SERVICE_FTP = 1)
, "uint", 0 ;dwFlags
, "uint", 0, "Ptr") ;dwContext
If (ErrorLevel != 0 or ic_hInternet = 0)
return 0
else
return 1
}
FtpClose() {
global ic_hInternet, io_hInternet, hModule
DllCall("wininet\InternetCloseHandle", "Ptr", ic_hInternet)
DllCall("wininet\InternetCloseHandle", "Ptr", io_hInternet)
DllCall("FreeLibrary", "Ptr", hModule)
}
Так как никто не отвечает, то отвечу себе сам.
1) Как я понял зависит от настроек сервера. Нужно настраивать так чтобы сразу файл заливался без всяких временных файлов. Стереть темповый файл .pureftpd-upload* никак не получается.
В принципе этот вопрос волнует меня больше всего - как стереть файл с фтп по маске.
2) Наверное данным скриптом невозможно.
3) Опять же разделить не получится, единственный вариант, что если после "msgbox, Нету места" следует "msgbox, Пропал инет" - значит все-таки дело в пропаже инета.
4) Походу в данный скрипт очень сложно.
Если есть у кого-то дополнения касаемо первого пункта - буду рад помощи!
В общем, оказалось все это очень геморно.
Скрипт устаревший, поэтому лучше использовать
http://www.autohotkey.com/board/topic/6 … -as-1-2-3/
1) У него нету бага с темповыми файлами .pureftpd-upload
2) У него есть счетчик заливки.
Но самого скрипта на оффсайте почему-то уже нету.
Поэтому через гугл нашел тут
https://github.com/george2/ahk-libs/tree/master/FTPv2
Но в скрипте досадный баг - для файлов больше, чем один гиг возвращет неверный размер - показывает "-1".
Плюс ко всему скорость закачки у скрипта в 5 раз!!! меньше чем у того же filezilla.
Пришлось искать по инету утилитки, которые размер определяют - в итоге только одна!!! определяет размер правильно.
Кстати состряпанная на autoit
http://creator-lab.ucoz.ru/load/4-1-0-37
Дабы не плодить новые темы: настроил работу с FTP по статье "FTP as easy as 1-2-3", но возникла проблема с отправленными на FTP файлами - у них всех размер 0. Согласно рекомендаций перевел в пассивный режим работы, но все равно отправленные файлы имеют нулевой размер.
в FTPv2.ahk - this.InternetConnectFlags := 0x08000000 (включен пассивный режим), коннект устанавливается, файлики удаляются, т.е. взаимодействие есть.
Можно прикрутить виндовую стандартную утилиту ftp, или какую-то другую, но хотелось бы решить задачу с привлечением минимального количества сторонних софтин.
Кто сталкивался с такой ситуацией?
Пардон, заработался, все функционирует..
Имеется функция определяющая размер файла , лежащего на фтп:
MsgBox % InternetFileGetSize( "ftp://ftp.winzip.com/testdown/testdown.htm" )
MsgBox % InternetFileGetSize( "http://ahkscript.org/favicon.ico" )
InternetFileGetSize( URL ) {
hMod := DllCall( "LoadLibrary", WStr, "wininet.dll" )
hIO := DllCall( "wininet\InternetOpenW"
, WStr, "Microsoft Internet Explorer"
, UInt, 4 ; INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY
, Int, 0, Int, 0, UInt, 0 )
hIU := DllCall( "wininet\InternetOpenUrlW"
, UInt, hIO, WStr, URL, Int, 0, Int, 0
, UInt, 0x84000000 ; INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD
, UInt, 0 )
If ( hIO & hIU )
If ( SubStr( URL,1,4 ) = "ftp:" )
FileSize := DllCall( "wininet\FtpGetFileSize", UInt,hIU, UIntP,0, UInt )
Else DllCall( "wininet\HttpQueryInfoW"
, UInt, hIU
, UInt, 0x20000005 ; HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER
, UIntP, FileSize, UIntP,4, Int,0 )
DllCall( "wininet\InternetCloseHandle", UInt, hIU )
DllCall( "wininet\InternetCloseHandle", UInt, hIO )
DllCall( "FreeLibrary", UInt, hMod )
Return FileSize
}
Но если файл более 4 гигов она возвращает неверный размер, равный остатку от деления на 4гб.
На autoit нашли решение:
https://www.autoitscript.com/forum/topi … ent-439706
Mhhh. I seem to have had problems reading yesterday.
I see what this is now.
The file size could be larger than can be given by a 32 bit integer. But the return value is an integer. So part of the size is returned in the second parameter.
So this is what I think is needed.
Local $High = dllstructCreate(("uint")
Local $pHigh = dllstructgetptr($High)
Local $ai_FTPGetFileSize = DllCall('wininet.dll', 'int', 'FtpGetFileSize', 'long', $ai_FTPGetSizeHandle[0], 'long_ptr', $pHigh )
$ai_FTPGetFileSize = $ai_FTPGetFileSize[0] + DllStructGetData($High,1) * (2^32)
Как бы его вставить в код ahk?
Вот так:
size1:=InternetFileGetSize("ftp://speedtest:speedtest@ftp.otenet.gr/test5Gb-a.db")
size2:=InternetFileGetSize("ftp://speedtest:speedtest@ftp.otenet.gr/test10Gb.db")
size3:=InternetFileGetSize("ftp://speedtest:speedtest@ftp.otenet.gr/test100Mb.db")
sizeGB1:=round(size1/(1024**3),2) " GB"
sizeGB2:=round(size2/(1024**3),2) " GB"
sizeMB:=round(size3/(1024**2),2) " MB"
msgbox % sizeGB1 "`n" sizeGB2 "`n" sizeMB "`n`n" size " Bytes`n" round(size/(1024**3),2) " GB"
InternetFileGetSize( URL ) {
hMod := DllCall( "LoadLibrary", WStr, "wininet.dll" )
hIO := DllCall( "wininet\InternetOpenW"
, WStr, "Microsoft Internet Explorer"
, UInt, 4 ; INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY
, Int, 0, Int, 0, UInt, 0 )
hIU := DllCall( "wininet\InternetOpenUrlW"
, UInt, hIO, WStr, URL, Int, 0, Int, 0
, UInt, 0x84000000 ; INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD
, UInt, 0 )
If ( hIO & hIU )
If ( SubStr( URL,1,4 ) = "ftp:" )
{
varSetCapacity(huint,4)
FileSize:=DllCall( "wininet\FtpGetFileSize", UInt,hIU,UInt,&huint,UInt)
FileSize := FileSize + (NumGet(huint)*(2**32))
}
Else DllCall( "wininet\HttpQueryInfoW"
, UInt, hIU
, UInt, 0x20000005 ; HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER
, UIntP, FileSize, UIntP,4, Int,0 )
DllCall( "wininet\InternetCloseHandle", UInt, hIU )
DllCall( "wininet\InternetCloseHandle", UInt, hIO )
DllCall( "FreeLibrary", UInt, hMod )
Return FileSize
}
Подытожу свои поиски.
В winscp есть все необходимое для работы с ftp, sftp.
И лог можно вывести в xml формате и хеш посчитать, если надо.
https://winscp.net/eng/index.php
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться