1 (изменено: Malcev, 2013-01-16 20:39:16)

Тема: AHK: FTP Работа с фтп

Как узнать размер файла лежащего на фтп, не скачивая его.
Мне нужно  удостовериться, что файл залит целиком.

2

Re: AHK: FTP Работа с фтп

Вот здесь посмотри. Только нужно перевести на "современный" AHK.

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

3 (изменено: Malcev, 2013-01-16 21:12:40)

Re: AHK: FTP Работа с фтп

Вот так работает.
Но 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) 
}

4 (изменено: Malcev, 2013-01-17 05:31:22)

Re: AHK: FTP Работа с фтп

Так как никто не отвечает, то отвечу себе сам.

1) Как я понял зависит от настроек сервера. Нужно настраивать так чтобы сразу файл заливался без всяких временных файлов. Стереть темповый файл .pureftpd-upload* никак не получается.
В принципе этот вопрос волнует меня больше всего - как стереть файл с фтп по маске.

2) Наверное данным скриптом невозможно.

3) Опять же разделить не получится, единственный вариант, что если после  "msgbox, Нету места" следует "msgbox, Пропал инет" - значит все-таки дело в пропаже инета.

4) Походу в данный скрипт очень сложно.

Если есть у кого-то дополнения касаемо первого пункта - буду рад помощи!

5 (изменено: Malcev, 2013-01-18 18:49:51)

Re: AHK: FTP Работа с фтп

В общем, оказалось все это очень геморно.
Скрипт устаревший, поэтому лучше использовать
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

6 (изменено: emmetoya, 2014-10-02 13:50:44)

Re: AHK: FTP Работа с фтп

Дабы не плодить новые темы: настроил работу с FTP по статье "FTP as easy as 1-2-3", но возникла проблема с отправленными на FTP файлами - у них всех размер 0. Согласно рекомендаций перевел в пассивный режим работы, но все равно отправленные файлы имеют нулевой размер.

в FTPv2.ahk - this.InternetConnectFlags := 0x08000000 (включен пассивный режим), коннект устанавливается, файлики удаляются, т.е. взаимодействие есть.
Можно прикрутить виндовую стандартную утилиту ftp, или какую-то другую, но хотелось бы решить задачу с привлечением минимального количества сторонних софтин.

Кто сталкивался с такой ситуацией?
Пардон, заработался, все функционирует..

7 (изменено: Malcev, 2015-09-08 17:27:36)

Re: AHK: 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?

8

Re: AHK: FTP Работа с фтп

Вот так:

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
}

9

Re: AHK: FTP Работа с фтп

Подытожу свои поиски.
В winscp есть все необходимое для работы с ftp, sftp.
И лог можно вывести в xml формате и хеш посчитать, если надо.
https://winscp.net/eng/index.php