Skip to content

An Elixir SFTP Client that wraps Erlang's ssh and ssh_sftp.

License

Notifications You must be signed in to change notification settings

tlux/sftp_client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

0ffec39 · Aug 5, 2024
Feb 24, 2024
Feb 24, 2024
Aug 5, 2024
Aug 2, 2024
Sep 25, 2020
May 6, 2019
Feb 24, 2024
Feb 24, 2024
May 28, 2021
Aug 5, 2024
Sep 6, 2019
Apr 15, 2024
Aug 5, 2024
Mar 25, 2024

Repository files navigation

SFTP Client

Build Coverage Status Module Version Hex Docs Total Download License Last Updated

An Elixir SFTP Client that wraps Erlang's ssh and ssh_sftp.

Prerequisites

  • Erlang 24 or greater
  • Elixir 1.11 or greater

Installation

The package can be installed by adding :sftp_client to your list of dependencies in mix.exs:

def deps do
  [
    {:sftp_client, "~> 2.1"}
  ]
end

Usage

There are bang (!) counterparts for almost all available functions.

Connect & Disconnect

To open a new connection to an SFTP server:

{:ok, conn} = SFTPClient.connect(host: "ftp.myhost.com")

Due to a change in OTP 24 that removed automatic public key lookup in the sftp module you may need to define the modify_algorithms option to avoid "Key exchange failed" errors:

{:ok, conn} = SFTPClient.connect(
  host: "ftp.myhost.com",
  modify_algorithms: [
    append: [
      public_key: [:"ssh-rsa"]
    ]
  ]
)

Refer to the docs for SFTPClient.Operations.Connect.connect/1 to find out all available options.

It is strongly recommended to close a connection after your operations have completed:

SFTPClient.disconnect(conn)

For short-lived connections you can also use a function as second argument. After the function body has run or raises, the connection is automatically closed.

SFTPClient.connect([host: "ftp.myhost.com"], fn conn ->
  # Do something with conn
end)

Download

To download a file from the server you can use the following function.

SFTPClient.download_file(conn, "my/remote/dir/file.jpg", "my/dir/local-file.jpg")
# => {:ok, "my/dir/local-file.jpg"}

When the third argument is an existing directory on your file system, the file is downloaded to a file with the same name as the one on the server.

SFTPClient.download_file(conn, "my/remote/dir/image.png", "my/local/dir")
# => {:ok, "my/local/dir/image.png"}

It is also possible to use Streams to download data into a file or memory.

source_stream = SFTPClient.stream_file!(conn, "my/remote/file.jpg")
target_stream = File.stream!("my/local/file.jpg")

source_stream
|> Stream.into(target_stream)
|> Stream.run()

Upload

To upload are file from the file system you can use the following function.

SFTPClient.upload_file(conn, "my/local/dir/file.jpg", "my/remote/dir/file.jpg")
# => {:ok, "my/remote/dir/file.jpg"}

You can also use Streams to upload data. Please make sure to set a proper chunk size or the upload may be very slow.

source_stream = File.stream!("my/local/file.jpg", [], 32_768)
target_stream = SFTPClient.stream_file!(conn, "my/remote/file.jpg")

source_stream
|> Stream.into(target_stream)
|> Stream.run()

List Directory

SFTPClient.list_dir(conn, "my/dir")
# => {:ok, ["my/dir/file_1.jpg", "my/dir/file_2.jpg", ...]}

Create Directory

SFTPClient.make_dir(conn, "my/new/dir")

Note that this operation fails unless the parent directory exists.

Delete

To delete a file:

SFTPClient.delete_file(conn, "my/remote/file.jpg")

To delete a directory:

SFTPClient.delete_dir(conn, "my/remote/dir")

Note that a directory cannot be deleted as long as it still contains files.

Rename

To move/rename a file or directory:

SFTPClient.rename(conn, "my/remote/file.jpg", "my/remote/new-file.jpg")

File Info

You can retrieve meta data about a file from the server such as file size, modification time, file permissions, owner and so on.

SFTPClient.file_info(conn, "my/remote/file.jpg")
# => {:ok, %File.Stat{...}}

Refer to the File.Stat docs for a list of available file information.

Symbolic Links

There are also a couple of functions that handle symlinks.

It is possible to get the target of a symlink.

SFTPClient.read_link(conn, "my/remote/link.jpg")
# => {:ok, "my/remote/file.jpg"}

You can retrieve meta data about symlinks, similar to file_info/2.

SFTPClient.link_info(conn, "my/remote/link.jpg")
# => {:ok, %File.Stat{...}}

And you are able to create symlinks.

SFTPClient.make_link(conn, "my/remote/link.jpg", "my/remote/file.jpg")

License

This library is released under the MIT License. See the LICENSE.md file for further details.