asyncftpclient
This module implements an asynchronous FTP client. It allows you to connect to an FTP server and perform operations on it such as for example:
- The upload of new files.
- The removal of existing files.
- Download of files.
- Changing of files' permissions.
- Navigation through the FTP server's directories.
Connecting to an FTP server
In order to begin any sort of transfer of files you must first connect to an FTP server. You can do so with the connect
procedure.
import asyncdispatch, asyncftpclient proc main() {.async.} = var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test") await ftp.connect() echo("Connected") waitFor(main())
A new main
async procedure must be declared to allow the use of the await
keyword. The connection will complete asynchronously and the client will be connected after the await ftp.connect()
call.
Uploading a new file
After a connection is made you can use the store
procedure to upload a new file to the FTP server. Make sure to check you are in the correct working directory before you do so with the pwd
procedure, you can also instead specify an absolute path.
import asyncdispatch, asyncftpclient proc main() {.async.} = var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test") await ftp.connect() let currentDir = await ftp.pwd() assert currentDir == "/home/user/" await ftp.store("file.txt", "file.txt") echo("File finished uploading") waitFor(main())
Checking the progress of a file transfer
The progress of either a file upload or a file download can be checked by specifying a onProgressChanged
procedure to the store
or retrFile
procedures.
Procs that take an onProgressChanged
callback will call this every progressInterval
milliseconds.
import asyncdispatch, asyncftpclient proc onProgressChanged(total, progress: BiggestInt, speed: float) {.async.} = echo("Uploaded ", progress, " of ", total, " bytes") echo("Current speed: ", speed, " kb/s") proc main() {.async.} = var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test", progressInterval = 500) await ftp.connect() await ftp.store("file.txt", "/home/user/file.txt", onProgressChanged) echo("File finished uploading") waitFor(main())
Imports
Types
AsyncFtpClient = ref object csock*: AsyncSocket dsock*: AsyncSocket user*, pass*: string address*: string port*: Port progressInterval: int jobInProgress*: bool job*: FtpJob dsockConnected*: bool
- Source Edit
FtpJobType = enum JRetrText, JRetr, JStore
- Source Edit
FtpEventType = enum EvTransferProgress, EvLines, EvRetr, EvStore
- Source Edit
FtpEvent = object filename*: string case typ*: FtpEventType of EvLines: lines*: string ## Lines that have been transferred. of EvRetr, EvStore: ## Retr/Store operation finished. nil of EvTransferProgress: bytesTotal*: BiggestInt ## Bytes total. bytesFinished*: BiggestInt ## Bytes transferred. speed*: BiggestInt ## Speed in bytes/s currentJob*: FtpJobType ## The current job being performed.
- Event Source Edit
ReplyError = object of IOError
- Source Edit
ProgressChangedProc = proc (total, progress: BiggestInt; speed: float): Future[ void] {...}{.closure, gcsafe.}
- Source Edit
Procs
proc send(ftp: AsyncFtpClient; m: string): Future[TaintedString] {...}{. raises: [Exception, ValueError], tags: [RootEffect].}
-
Send a message to the server, and wait for a primary reply.
\c\L
is added for you.You need to make sure that the message
m
doesn't contain any newline characters. Failing to do so will raiseAssertionDefect
.Note: The server may return multiple lines of coded replies.
Source Edit proc connect(ftp: AsyncFtpClient): owned(Future[void]) {...}{.raises: [Exception], tags: [RootEffect].}
- Connect to the FTP server specified by
ftp
. Source Edit proc pwd(ftp: AsyncFtpClient): Future[TaintedString] {...}{. raises: [Exception, ValueError], tags: [RootEffect].}
- Returns the current working directory. Source Edit
proc cd(ftp: AsyncFtpClient; dir: string): owned(Future[void]) {...}{. raises: [Exception], tags: [RootEffect].}
- Changes the current directory on the remote FTP server to
dir
. Source Edit proc cdup(ftp: AsyncFtpClient): owned(Future[void]) {...}{.raises: [Exception], tags: [RootEffect].}
- Changes the current directory to the parent of the current directory. Source Edit
proc listDirs(ftp: AsyncFtpClient; dir = ""): Future[seq[string]] {...}{. raises: [Exception, ValueError], tags: [RootEffect].}
- Returns a list of filenames in the given directory. If
dir
is "", the current directory is used. Ifasync
is true, this function will return immediately and it will be your job to use asyncdispatch'spoll
to progress this operation. Source Edit proc fileExists(ftp: AsyncFtpClient; file: string): Future[bool] {...}{. raises: [Exception, ValueError], tags: [RootEffect].}
- Determines whether
file
exists. Source Edit proc createDir(ftp: AsyncFtpClient; dir: string; recursive = false): owned( Future[void]) {...}{.raises: [Exception], tags: [RootEffect].}
- Creates a directory
dir
. Ifrecursive
is true, the topmost subdirectory ofdir
will be created first, following the secondmost... etc. this allows you to give a full path as thedir
without worrying about subdirectories not existing. Source Edit proc chmod(ftp: AsyncFtpClient; path: string; permissions: set[FilePermission]): owned( Future[void]) {...}{.raises: [Exception], tags: [RootEffect].}
- Changes permission of
path
topermissions
. Source Edit proc list(ftp: AsyncFtpClient; dir = ""): Future[string] {...}{. raises: [Exception, ValueError], tags: [RootEffect].}
- Lists all files in
dir
. Ifdir
is""
, uses the current working directory. Source Edit proc retrText(ftp: AsyncFtpClient; file: string): Future[string] {...}{. raises: [Exception, ValueError], tags: [RootEffect].}
- Retrieves
file
. File must be ASCII text. Source Edit proc defaultOnProgressChanged(total, progress: BiggestInt; speed: float): Future[ void] {...}{.nimcall, gcsafe, raises: [Exception], tags: [RootEffect].}
- Default FTP
onProgressChanged
handler. Does nothing. Source Edit proc retrFile(ftp: AsyncFtpClient; file, dest: string; onProgressChanged: ProgressChangedProc = defaultOnProgressChanged): owned( Future[void]) {...}{.raises: [Exception], tags: [RootEffect, TimeEffect, WriteIOEffect].}
- Downloads
file
and saves it todest
. TheEvRetr
event is passed to the specifiedhandleEvent
function when the download is finished. The event'sfilename
field will be equal tofile
. Source Edit proc store(ftp: AsyncFtpClient; file, dest: string; onProgressChanged: ProgressChangedProc = defaultOnProgressChanged): owned( Future[void]) {...}{.raises: [Exception], tags: [RootEffect, ReadIOEffect, TimeEffect].}
- Uploads
file
todest
on the remote FTP server. Usage of this function asynchronously is recommended to view the progress of the download. TheEvStore
event is passed to the specifiedhandleEvent
function when the upload is finished, and thefilename
field will be equal tofile
. Source Edit proc rename(ftp: AsyncFtpClient; nameFrom: string; nameTo: string): owned( Future[void]) {...}{.raises: [Exception], tags: [RootEffect].}
- Rename a file or directory on the remote FTP Server from current name
name_from
to new namename_to
Source Edit proc removeFile(ftp: AsyncFtpClient; filename: string): owned(Future[void]) {...}{. raises: [Exception], tags: [RootEffect].}
- Delete a file
filename
on the remote FTP server Source Edit proc removeDir(ftp: AsyncFtpClient; dir: string): owned(Future[void]) {...}{. raises: [Exception], tags: [RootEffect].}
- Delete a directory
dir
on the remote FTP server Source Edit proc newAsyncFtpClient(address: string; port = Port(21); user, pass = ""; progressInterval: int = 1000): AsyncFtpClient {...}{. raises: [OSError, Exception], tags: [RootEffect].}
- Creates a new
AsyncFtpClient
object. Source Edit
© 2006–2021 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/asyncftpclient.html