[Class] FTP

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

[Class] FTP

Post by jNizM » 27 Jul 2020, 07:36

Class FTP
AutoHotkey wrapper for FTP Sessions (msdn-docs)


Source
Mirror: Release on GitHub

Code: Select all

; ===============================================================================================================================
; AutoHotkey wrapper for FTP Sessions
;
; Author ....: jNizM
; Released ..: 2020-07-26
; Modified ..: 2020-07-31
; Github ....: https://github.com/jNizM/Class_FTP
; Forum .....: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=79142
; ===============================================================================================================================


class FTP
{

	static hWININET := DllCall("LoadLibrary", "str", "wininet.dll", "ptr")


	; ===== PUBLIC METHODS ======================================================================================================

	Close(hInternet)
	{
		if (hInternet)
			if (this.InternetCloseHandle(hInternet))
				return true
		return false
	}


	Connect(hInternet, ServerName, Port := 21, UserName := "", Password := "", FTP_PASV := 1)
	{
		if (hConnect := this.InternetConnect(hInternet, ServerName, Port, UserName, Password, FTP_PASV))
			return hConnect
		return false
	}


	CreateDirectory(hConnect, Directory)
	{
		if (DllCall("wininet\FtpCreateDirectory", "ptr", hConnect, "ptr", &Directory))
			return true
		return false
	}


	DeleteFile(hConnect, FileName)
	{
		if (DllCall("wininet\FtpDeleteFile", "ptr", hConnect, "ptr", &FileName))
			return true
		return false
	}


	Disconnect(hConnect)
	{
		if (hConnect)
			if (this.InternetCloseHandle(hConnect))
				return true
		return false
	}


	FindFiles(hConnect, SearchFile := "*.*")
	{
		static FILE_ATTRIBUTE_DIRECTORY := 0x10

		Files := []
		find := this.FindFirstFile(hConnect, hEnum, SearchFile)
		if !(find.FileAttr & FILE_ATTRIBUTE_DIRECTORY)
			Files.Push(find)

		while (find := this.FindNextFile(hEnum))
			if !(find.FileAttr & FILE_ATTRIBUTE_DIRECTORY)
				Files.Push(find)
		this.Close(hEnum)
		return Files
	}


	FindFolders(hConnect, SubDirectories := "*.*")
	{
		static FILE_ATTRIBUTE_DIRECTORY := 0x10

		Folders := []
		find := this.FindFirstFile(hConnect, hEnum, SubDirectories)
		if (find.FileAttr & FILE_ATTRIBUTE_DIRECTORY)
			Folders.Push(find)
		while (find := this.FindNextFile(hEnum))
			if (find.FileAttr & FILE_ATTRIBUTE_DIRECTORY)
				Folders.Push(find)
		this.Close(hEnum)
		return Folders
	}


	GetCurrentDirectory(hConnect)
	{
		static MAX_PATH := 260 + 8

		BUFFER_SIZE := VarSetCapacity(CurrentDirectory, MAX_PATH, 0)
		if (DllCall("wininet\FtpGetCurrentDirectory", "ptr", hConnect, "ptr", &CurrentDirectory, "uint*", BUFFER_SIZE))
			return StrGet(&CurrentDirectory)
		return false
	}


	GetFile(hConnect, RemoteFile, NewFile, OverWrite := 0, Flags := 0)
	{
		if (DllCall("wininet\FtpGetFile", "ptr", hConnect, "ptr", &RemoteFile, "ptr", &NewFile, "int", !OverWrite, "uint", 0, "uint", Flags, "uptr", 0))
			return true
		return false
	}


	GetFileSize(hConnect, FileName, SizeFormat := "auto", SizeSuffix := false)
	{
		static GENERIC_READ := 0x80000000

		if (hFile := this.OpenFile(hConnect, FileName, GENERIC_READ))
		{
			VarSetCapacity(FileSizeHigh, 8)
			if (FileSizeLow := DllCall("wininet\FtpGetFileSize", "ptr", hFile, "uint*", FileSizeHigh, "uint"))
			{
				this.InternetCloseHandle(hFile)
				return this.FormatBytes(FileSizeLow + (FileSizeHigh << 32), SizeFormat, SizeSuffix)
			}
			this.InternetCloseHandle(hFile)
		}
		return false
	}


	Open(Agent, Proxy := "", ProxyBypass := "")
	{
		if (hInternet := this.InternetOpen(Agent, Proxy, ProxyBypass))
			return hInternet
		return false
	}


	PutFile(hConnect, LocaleFile, RemoteFile, Flags := 0)
	{
		if (DllCall("wininet\FtpPutFile", "ptr", hConnect, "ptr", &LocaleFile, "ptr", &RemoteFile, "uint", Flags, "uptr", 0))
			return true
		return false
	}


	RemoveDirectory(hConnect, Directory)
	{
		if (DllCall("wininet\FtpRemoveDirectory", "ptr", hConnect, "ptr", &Directory))
			return true
		return false
	}


	RenameFile(hConnect, ExistingFile, NewFile)
	{
		if (DllCall("wininet\FtpRenameFile", "ptr", hConnect, "ptr", &ExistingFile, "ptr", &NewFile))
			return true
		return false
	}


	SetCurrentDirectory(hconnect, Directory)
	{
		if (DllCall("wininet\FtpSetCurrentDirectory", "ptr", hConnect, "ptr", &Directory))
			return true
		return false
	}


	; ===== PRIVATE METHODS =====================================================================================================

	FileAttributes(Attributes)
	{
		static FILE_ATTRIBUTE := { 0x1: "READONLY", 0x2: "HIDDEN", 0x4: "SYSTEM", 0x10: "DIRECTORY", 0x20: "ARCHIVE", 0x40: "DEVICE", 0x80: "NORMAL"
						, 0x100: "TEMPORARY", 0x200: "SPARSE_FILE", 0x400: "REPARSE_POINT", 0x800: "COMPRESSED", 0x1000: "OFFLINE"
						, 0x2000: "NOT_CONTENT_INDEXED", 0x4000: "ENCRYPTED", 0x8000: "INTEGRITY_STREAM", 0x10000: "VIRTUAL"
						, 0x20000: "NO_SCRUB_DATA", 0x40000: "RECALL_ON_OPEN", 0x400000: "RECALL_ON_DATA_ACCESS" }
		GetFileAttributes := []
		for k, v in FILE_ATTRIBUTE
			if (k & Attributes)
				GetFileAttributes.Push(v)
		return GetFileAttributes
	}


	FindData(ByRef WIN32_FIND_DATA, SizeFormat := "auto", SizeSuffix := false)
	{
		static MAX_PATH := 260
		static MAXDWORD := 0xffffffff

		addr := &WIN32_FIND_DATA
		FIND_DATA := []
		FIND_DATA["FileAttr"]          := NumGet(addr + 0, "uint")
		FIND_DATA["FileAttributes"]    := this.FileAttributes(NumGet(addr + 0, "uint"))
		FIND_DATA["CreationTime"]      := this.FileTime(NumGet(addr +  4, "uint64"))
		FIND_DATA["LastAccessTime"]    := this.FileTime(NumGet(addr + 12, "uint64"))
		FIND_DATA["LastWriteTime"]     := this.FileTime(NumGet(addr + 20, "uint64"))
		FIND_DATA["FileSize"]          := this.FormatBytes((NumGet(addr + 28, "uint") * (MAXDWORD + 1)) + NumGet(addr + 32, "uint"), SizeFormat, SizeSuffix)
		FIND_DATA["FileName"]          := StrGet(addr + 44, "utf-16")
		FIND_DATA["AlternateFileName"] := StrGet(addr + 44 + MAX_PATH * (A_IsUnicode ? 2 : 1), "utf-16")
		return FIND_DATA
	}


	FindFirstFile(hConnect, ByRef hFind, SearchFile := "*.*", SizeFormat := "auto", SizeSuffix := false)
	{
		VarSetCapacity(WIN32_FIND_DATA, (A_IsUnicode ? 592 : 320), 0)
		if (hFind := DllCall("wininet\FtpFindFirstFile", "ptr", hConnect, "str", SearchFile, "ptr", &WIN32_FIND_DATA, "uint", 0, "uint*", 0))
			return this.FindData(WIN32_FIND_DATA, SizeFormat, SizeSuffix)
		VarSetCapacity(WIN32_FIND_DATA, 0)
		return false
	}


	FindNextFile(hFind, SearchFile := "*.*", SizeFormat := "auto", SizeSuffix := false)
	{
		VarSetCapacity(WIN32_FIND_DATA, (A_IsUnicode ? 592 : 320), 0)
		if (DllCall("wininet\InternetFindNextFile", "ptr", hFind, "ptr", &WIN32_FIND_DATA))
			return this.FindData(WIN32_FIND_DATA, SizeFormat, SizeSuffix)
		VarSetCapacity(WIN32_FIND_DATA, 0)
		return false
	}


	FileTime(addr)
	{
		this.FileTimeToSystemTime(addr, SystemTime)
		this.SystemTimeToTzSpecificLocalTime(&SystemTime, LocalTime)
		return Format("{:04}{:02}{:02}{:02}{:02}{:02}"
					, NumGet(LocalTime,  0, "ushort")
					, NumGet(LocalTime,  2, "ushort")
					, NumGet(LocalTime,  6, "ushort")
					, NumGet(LocalTime,  8, "ushort")
					, NumGet(LocalTime, 10, "ushort")
					, NumGet(LocalTime, 12, "ushort"))
	}


	FileTimeToSystemTime(FileTime, ByRef SystemTime)
	{
		VarSetCapacity(SystemTime, 16, 0)
		if (DllCall("FileTimeToSystemTime", "int64*", FileTime, "ptr", &SystemTime))
			return true
		return false
	}


	FormatBytes(bytes, SizeFormat := "auto", suffix := false)
	{
		static SFBS_FLAGS_ROUND_TO_NEAREST_DISPLAYED_DIGIT    := 0x0001
		static SFBS_FLAGS_TRUNCATE_UNDISPLAYED_DECIMAL_DIGITS := 0x0002
		static S_OK := 0

		if (SizeFormat = "auto")
		{
			size := VarSetCapacity(buf, 1024, 0)
			if (DllCall("shlwapi\StrFormatByteSizeEx", "int64", bytes, "int", SFBS_FLAGS_ROUND_TO_NEAREST_DISPLAYED_DIGIT, "str", buf, "uint", size) = S_OK)
				output := buf
		}
		else if (SizeFormat = "kilobytes" || SizeFormat = "kb")
			output := Round(bytes / 1024, 2) . (suffix ? " KB" : "")
		else if (SizeFormat = "megabytes" || SizeFormat = "mb")
			output := Round(bytes / 1024**2, 2) . (suffix ? " MB" : "")
		else if (SizeFormat = "gigabytes" || SizeFormat = "gb")
			output := Round(bytes / 1024**3, 2) . (suffix ? " GB" : "")
		else if (SizeFormat = "terabytes" || SizeFormat = "tb")
			output := Round(bytes / 1024**4, 2) . (suffix ? " TB" : "")
		else
			output := Round(bytes, 2) . (suffix ? " Bytes" : "")
		return output
	}


	InternetCloseHandle(hInternet)
	{
		if (DllCall("wininet\InternetCloseHandle", "ptr", hInternet))
			return true
		return false
	}


	InternetConnect(hInternet, ServerName, Port := 21, UserName := "", Password := "", FTP_PASV := 1)
	{
		static INTERNET_DEFAULT_FTP_PORT := 21
		static INTERNET_SERVICE_FTP      := 1
		static INTERNET_FLAG_PASSIVE     := 0x08000000

		if (hConnect := DllCall("wininet\InternetConnect", "ptr",    hInternet
														 , "ptr",    &ServerName
														 , "ushort", (Port = 21 ? INTERNET_DEFAULT_FTP_PORT : Port)
														 , "ptr",    (UserName ? &UserName : 0)
														 , "ptr",    (Password ? &Password : 0)
														 , "uint",   INTERNET_SERVICE_FTP
														 , "uint",   (FTP_PASV ? INTERNET_FLAG_PASSIVE : 0)
														 , "uptr",   0
														 , "ptr"))
			return hConnect
		return false
	}


	InternetOpen(Agent, Proxy := "", ProxyBypass := "")
	{
		static INTERNET_OPEN_TYPE_DIRECT := 1
		static INTERNET_OPEN_TYPE_PROXY  := 3

		if (hInternet := DllCall("wininet\InternetOpen", "ptr",  &Agent
													   , "uint", (Proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_DIRECT)
													   , "ptr",  (Proxy ? &Proxy : 0)
													   , "ptr",  (ProxyBypass ? &ProxyBypass : 0)
													   , "uint", 0
													   , "ptr"))
			return hInternet
		return false
	}


	OpenFile(hConnect, FileName, Access)
	{
		static FTP_TRANSFER_TYPE_BINARY := 2

		if (hFTPSESSION := DllCall("wininet\FtpOpenFile", "ptr", hConnect, "ptr", &FileName, "uint", Access, "uint", FTP_TRANSFER_TYPE_BINARY, "uptr", 0))
			return hFTPSESSION
		return false
	}


	SystemTimeToTzSpecificLocalTime(SystemTime, ByRef LocalTime)
	{
		VarSetCapacity(LocalTime, 16, 0)
		if (DllCall("SystemTimeToTzSpecificLocalTime", "ptr", 0, "ptr", SystemTime, "ptr", &LocalTime))
			return true
		return false
	}

}

; ===============================================================================================================================

Questions / Bugs / Issues
If you notice any kind of bugs or issues, report them here. Same for any kind of questions.


Copyright and License
The Unlicense
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile

User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [Class] FTP

Post by jNizM » 27 Jul 2020, 07:36

Examples
Writes a file to the server.

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
FTP.PutFile(hSession, "C:\Temp\testfile.txt", "testfile.txt")
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Retrieves a file from the server.

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
FTP.GetFile(hSession, "testfile.txt", "C:\Temp\testfile.txt")
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Retrieves the file size of the requested FTP resource.

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
MsgBox % FTP.GetFileSize(hSession, "testfile.txt")
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Deletes a file from the server.

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
FTP.DeleteFile(hSession, "testfile.txt")
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Creates a new directory on the server.

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
FTP.CreateDirectory(hSession, "Test_Folder")
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Changes the client's current directory on the server.

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
FTP.SetCurrentDirectory(hSession, "Test_Folder")
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Returns the client's current directory on the server.

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
MsgBox % FTP.GetCurrentDirectory(hSession)
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Deletes a directory on the server.

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
FTP.RemoveDirectory(hSession, "Test_Folder")
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Enumerate all Files in root directory. (!!! EXPERIMENTAL !!!)

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
for k, File in FTP.FindFiles(hSession)
	MsgBox % File.FileName
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Enumerate all Files in a subdirectory. (!!! EXPERIMENTAL !!!)

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
for k, File in FTP.FindFiles(hSession, "/Folder 2")
	MsgBox % File.FileName
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Enumerate all Folders in root directory. (!!! EXPERIMENTAL !!!)

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
for k, Folder in FTP.FindFolders(hSession)
	MsgBox % Folder.FileName
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Enumerate all Folders in a subdirectory. (!!! EXPERIMENTAL !!!)

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
for k, Folder in FTP.FindFolders(hSession, "/Folder 2")
	MsgBox % Folder.FileName
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Todo
- FtpFindFirstFile
- InternetFindNextFile
- InternetReadFile
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile

Tre4shunter
Posts: 139
Joined: 26 Jan 2016, 16:05

Re: [Class] FTP

Post by Tre4shunter » 27 Jul 2020, 08:18

Very Nice!

Was just looking like something like this for a project - i will be updating :)

Also a nice little Class/dllcall demo!

Thanks!

ahk7
Posts: 575
Joined: 06 Nov 2013, 16:35

Re: [Class] FTP

Post by ahk7 » 28 Jul 2020, 11:20


User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [Class] FTP

Post by jNizM » 29 Jul 2020, 00:37

ahk7 wrote:
28 Jul 2020, 11:20
Is the the updated version of https://github.com/jNizM/AHK_Scripts/blob/master/src/ftp/Class_FTP.ahk ?
Something like that. I'll delete the old one on GitHub as soon as the class is done here.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile

User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [Class] FTP

Post by jNizM » 30 Jul 2020, 07:49

Added FindFiles and FindFolders. Experimental! Please report bugs and issues.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile

ahk7
Posts: 575
Joined: 06 Nov 2013, 16:35

Re: [Class] FTP

Post by ahk7 » 13 Aug 2020, 16:39

I tested .FindFiles with a 30K+ files folder and works correctly as do other functions I tried. I'll try it in production next, but so far, so good.

User avatar
blackjoker
Posts: 18
Joined: 01 Dec 2020, 02:57

Re: [Class] FTP

Post by blackjoker » 07 Jun 2021, 13:22

Great work!!! Worked for me... Thank you!

User avatar
blackjoker
Posts: 18
Joined: 01 Dec 2020, 02:57

Re: [Class] FTP

Post by blackjoker » 09 Jun 2021, 09:46

Maybe someone could tell me, why these functions don't have filemove to other directory function? I dont want to use formula Download file then upload file to other dir, because it uses traffic. Where am i wrong? How do you move files from one FTP dir to other FTP dir?

User avatar
blackjoker
Posts: 18
Joined: 01 Dec 2020, 02:57

Re: [Class] FTP

Post by blackjoker » 13 Jun 2021, 05:44

I had an issue, when repeatedly downloading files from FTP server. :?: When code checks server every 20 seconds, and downloads smth it starts to download from Win Cache :think: even if in server file have been deleted.
So for me helps additionals flags :dance: in method:

Code: Select all

	FindFiles(hConnect, SearchFile := "*.*")
	{
		static FILE_ATTRIBUTE_DIRECTORY := 0x10
		static INTERNET_FLAG_RELOAD := 0x80000000
		static INTERNET_FLAG_DONT_CACHE := 0x04000000
		

		Files := []
		
		find := this.FindFirstFile(hConnect, hEnum, SearchFile)
		if !(find.FileAttr & FILE_ATTRIBUTE_DIRECTORY & INTERNET_FLAG_NO_CACHE_WRITE & INTERNET_FLAG_RELOAD)
			Files.Push(find)

		while (find := this.FindNextFile(hEnum))
			if !(find.FileAttr & FILE_ATTRIBUTE_DIRECTORY & INTERNET_FLAG_NO_CACHE_WRITE & INTERNET_FLAG_RELOAD)
				Files.Push(find)
		this.Close(hEnum)
		find := 
		return Files
	}
From msdocs:
https://docs.microsoft.com/en-us/windows/win32/wininet/ftp-sessions
"If the application makes changes on the FTP server or if the FTP server changes frequently, the INTERNET_FLAG_NO_CACHE_WRITE and INTERNET_FLAG_RELOAD flags should be set in FtpFindFirstFile. These flags ensure that the directory information being retrieved from the FTP server is current."

User avatar
boiler
Posts: 16902
Joined: 21 Dec 2014, 02:44

Re: [Class] FTP

Post by boiler » 13 Jun 2021, 06:35

blackjoker wrote: Maybe someone could tell me, why these functions don't have filemove to other directory function?
It’s open source, so there’s nothing stopping you from adding that capability. I take it from how you stated your question (as opposed to a feature request) that you consider it is so trivial to add it that there is no reason it shouldn’t be there already.

User avatar
blackjoker
Posts: 18
Joined: 01 Dec 2020, 02:57

Re: [Class] FTP

Post by blackjoker » 13 Jun 2021, 08:16

boiler wrote:
13 Jun 2021, 06:35
blackjoker wrote: Maybe someone could tell me, why these functions don't have filemove to other directory function?
It’s open source, so there’s nothing stopping you from adding that capability. I take it from how you stated your question (as opposed to a feature request) that you consider it is so trivial to add it that there is no reason it shouldn’t be there already.
Well it was strange to me that there is no such thing and i thought i just missed something. I wanted to use MOVE file in server for backup insted DELETE it forever. And i dont want to use additional traffic for downloading file then UPLOADING file for backup purpose.
boiler from ypur post i understood that it is very hard to code file MOVE inside FTP and there is no function for that.


User avatar
blackjoker
Posts: 18
Joined: 01 Dec 2020, 02:57

Re: [Class] FTP

Post by blackjoker » 13 Jun 2021, 10:28

:superhappy:
Thank you malcev!

... :facepalm: on myself...

User avatar
blackjoker
Posts: 18
Joined: 01 Dec 2020, 02:57

Re: [Class] FTP

Post by blackjoker » 14 Jun 2021, 10:29

Nothing special, but for me that was a cost of 2-3 days searching... so maybe helps for someone:

Moves file to another FTP location (changes dir location):

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
FTP.RenameFile(hSession, "/existing/directory/old_file_name.ext", "/future/directory/new_file_name.ext")
FTP.Disconnect(hSession)
FTP.Close(hFTP)
Renames file in FTP (changes only file name):

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
FTP.RenameFile(hSession, "/existing/directory/old_file_name.ext", "/existing/directory/new_file_name.ext")
FTP.Disconnect(hSession)
FTP.Close(hFTP)

HeXaDeCiMaToR
Posts: 155
Joined: 08 Feb 2021, 12:42

Re: [Class] FTP

Post by HeXaDeCiMaToR » 27 May 2022, 09:55

I'm having issues connecting to an SFTP - SSH Server. Will this Class work with SFTP - SSH?

ahk7
Posts: 575
Joined: 06 Nov 2013, 16:35

Re: [Class] FTP

Post by ahk7 » 27 May 2022, 12:02

HeXaDeCiMaToR wrote:
27 May 2022, 09:55
I'm having issues connecting to an SFTP - SSH Server. Will this Class work with SFTP - SSH?
Have you tried the WinSCP library https://github.com/lipkau/WinSCP.ahk

wozas123
Posts: 1
Joined: 05 Jul 2022, 08:04

Re: [Class] FTP

Post by wozas123 » 12 Jul 2022, 08:18

Code: Select all

XX = %dd%

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "XXXX, 21, "XXX", "XXX")
FTP.PutFile(hSession, "D:\%dd%.txt", "/sdb1/00/00.txt")
FTP.Disconnect(hSession)
FTP.Close(hFTP)

no way to use variables
It doesn't make sense to use
only send one by one

hd0202
Posts: 183
Joined: 04 Oct 2013, 03:07
Location: Germany near Cologne

Re: [Class] FTP

Post by hd0202 » 12 Jul 2022, 10:35

try:

Code: Select all

FTP.PutFile(hSession, "D:\" . dd . ".txt", "/sdb1/00/00.txt")  ; it is an expression !
Hubert

ShatterCoder
Posts: 73
Joined: 06 Oct 2016, 15:57

Re: [Class] FTP

Post by ShatterCoder » 09 Jun 2023, 15:39

I'd like to submit an addition to the class: FIleRead() which allows you to read a file from the FTP server directly to a variable without needing to write to disk.

Code: Select all

ReadFile(hConnect, FileName)
	{
		static GENERIC_READ := 0x80000000
		if (hFile := this.OpenFile(hConnect, FileName, GENERIC_READ))
		{
			data_out := ""
			chunksize := 1024 ;chunk size to request per dllcall
			VarSetCapacity(buf, chunksize ) 
			VarSetCapacity(bytes_read, 4 * 4) ;dword
			bytes_read := 0
			while (DllCall("wininet\InternetReadFile", "ptr", hFile, "Uptr", &buf, "uint", chunksize , "ptr", &bytes_read) && bytes_read)
				data_out .= StrGet(&Buf + 0, "UTF-8")
			this.InternetCloseHandle(hFile)
			return data_out
		}
		return false
	}
I'm not sure how many people will have need of this particular method, but for myself it was needed because I was having to look through multiple files on an FTP server per second to look for a specific string so avoiding disk read/write time was essential.

example usage:

Code: Select all

hFTP := FTP.Open("AHK-FTP")
hSession := FTP.Connect(hFTP, "ftp.example.com", 21, "user", "passwd")
Filecontent := FTP.ReadFile(hSession, "testfile.txt")
msgbox, % Filecontent
FTP.Disconnect(hSession)
FTP.Close(hFTP)

Post Reply

Return to “Scripts and Functions (v1)”