Paramiko- How to transfer files with Remote System (SFTP Servers) using Python

KIHSA Rai
Nerd For Tech
Published in
5 min readAug 14, 2023

A comprehensive guide on how to upload and download files from an SFTP-Server/ remove machine using paramiko

Photo by Cookie the Pom on Unsplash

Hello Jawans, 😎, today we will be learning about Sftp Server, Rebex Tiny SFTP Server, and Paramiko. Howzzzzz the Joshhhhhhhh …???… ⭐🤩🔥

¡Bcak Sroty

So, the backstory goes like this, I was working on a project where I wanted to download files from a remote SFTP Server 🖥️ and upload that file into another remote SFTP server. 💻

Well, there are multiple ways to do this. I can use SSH, curl, or use any SFTP Clients using either SFTP or SCP. I followed a different approach, I wanted to automate this process without any human intervention except for starting at the beginning.

I will use a Python script and Python modules Paramiko and PyCurl to achieve the requirement and to fully automate it will schedule the execution of the Python script at 8 a.m. every day.
Today we will be discussing about Paramiko

1. Paramiko Client

According to paramiko.org documentation. Paramiko is a Python implementation of SSHv2. It provides both client and server-side functionality. To connect to the remover server and transfer the file or perform any operations we need to create a Paramiko client as shown below.
SSH_Client= Paramiko.SSHClient()

2. Free SFTP Server

I’m using Rebex Tiny SFTP Server as my remote SFTP server. As you can see all the server details such as an address, port, username, password, and root directory, all are shared in the UI and once you start the Rebex server it will listen to the port for any request.
If you want to learn more about Rebex and how to configure it, then follow and write down in a comment.

Rebex Tiny SFTP Server UI

Download Rebex Tiny SFTP Server: link

3. Connect to the Remote Server

Once we have created Paramiko Client we can then use the username and password for authentication to connect to the server.
SSH_Client.connect(hostname=hostName, port= port, username=userName, password= password)
If you directly connect to the server, you will get an error because Paramiko is not sure whether the remote server is trustworthy or not. To avoid this, we need to setlook_for_keys flag and also add AutoPolicy.

import paramiko
SSH_Client= paramiko.SSHClient()
SSH_Client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
SSH_Client.connect( hostname=hostName, port=port, username=userName,
password= password, look_for_keys= false
)
Connecting to Rebex Tiny SFTP Server

4. Storing Credentials

It’s a very dangerous and bad coding exercise to hardcode the credentials. The best practice is to store the credentials in encrypted form. One of the simplest ways to store credentials is config files (.ini files). To learn about python configParse follow this link
Python ConfigParser: A Comprehensive Guide ⚙️ | by KIHSA Rai | Aug, 2023 | Medium

5. Downloading Files

To transfer files, we need to first create an SFTP session between the client and the server. We can do this by using the SSHClient that we have created earlier.
sftp_client= SSH_Client.open_sftp()
Once this is done then we can call the API
get(remoteFilePath, localFilePath) to download the file from the remote server to the local system (localFilePath).
Since I’m using the Rebex SFTP server the root directoryis the data folder. So, I will be downloading files from the root (data) directory itself.

sftp_client    = SSH_Client.open_sftp()
localFilePath = "temp/testfile.txt"
remoteFilePath = "testfile.txt"
try:
sftp_client.get(remoteFilePath, localFilePath)
except FileNotFoundError as err:
print(f"File: {remoteFilePath} was not found on the source server {self.__hostName}:{self.__port}")
sftp_client.close()

This will download the file testfile.txt from the data folder of the Rebex Server to the local system, inside the temp folder, with the same filename. Once the download is done we need to also close the session by calling close() function`.

6. Uploading Files

Similar to download we need to first create a SFTP session.
sftp_client= SSH_Client.open_sftp()
Once this is done then we can call the API
put(localFilePath, remoteFilePath) to upload the file from the local system (localFilePath) to the remote server.
Since I’m using the Rebex SFTP server the root directory is thedata folder. So, I will be uploading files to the root (data) directory itself.

sftp_client    = SSH_Client.open_sftp()
localFilePath = "temp/testfile.txt"
remoteFilePath = "testfile.txt"
try:
sftp_client.put(localFilePath, remoteFilePath)
except FileNotFoundError as err:
print(f"File {localFilePath} was not found on the local system")
sftp_client.close()

This will upload the file testfile.txt from the temp folder to the Rebex Servers root directory data with the same filename.

7. Listing the files

First, create the SFTP session and call the API listdir and provide the remoteFilePath

sftp_client= SSH_Client.open_sftp()
remoteFilePath= "."
try:
print(f"lists of files {sftp_client.listdir(remoteFilePath)}")
except err:
print(f"Error while getting the list of files")
Listing files in the Rebex SFTP Server

8. Executing remote Commands

To execute commands remotely you need to call API exec_command(). The API call returns a tuple of (stdin, stdout, stderr).
Since Rebex Tiny SFTP Server doesn’t allow shell subsystem, only SFTP connections, we can use Rebex Buru SFTP Server for this.
Download Rebex Buru SFTP Server — Rebex.NET

stdin,stdout,stderr= SSH_Client.exec_command(“ls”)
print(stdout.readlines())
print(stderr.readlines())

9. Combined Code

import paramiko
import os

class SFTPServerClient:

def __init__(self, hostname, port, username, password):
self.__hostName = hostname
self.__port = port
self.__userName = username
self.__password = password
self.__SSH_Client = paramiko.SSHClient()


def connect(self):
try:
self.__SSH_Client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.__SSH_Client.connect(
hostname = self.__hostName,
port = self.__port,
username = self.__userName,
password = self.__password,
look_for_keys =False
)
except Exception as excp:
raise Exception(excp)
return
else:
print(f"Connected to server {self.__hostName}:{self.__port} as
{self.__userName}.")


def disconnect(self):
self.__SSH_Client.close()
print(f"{self.__userName} is disconnected to server
{self.__hostName}:{self.__port}")


def getListofFiles(self, remoteFilePath):
sftp_client= self.__SSH_Client.open_sftp()
try:
print(f"lists of files {sftp_client.listdir(remoteFilePath)}")
except err:
print(f"Error while getting the list of files")


def downloadFiles(self, remoteFilePath):
localFilePath= os.path.join("temp",remoteFilePath)
print(f"downloading file {remoteFilePath} to remote {localFilePath}")

sftp_client=self.__SSH_Client.open_sftp()
try:
sftp_client.get(remoteFilePath, localFilePath)
except FileNotFoundError as err:
print(f"File: {remoteFilePath} was not found on the server")
sftp_client.close()


def uploadFiles(self, remoteFilePath, localFilePath):
localFilePath= os.path.join("temp",remoteFilePath)
print(f"uploading file {localFilePath} to remote {remoteFilePath}")

sftp_client=self.__SSH_Client.open_sftp()
try:
sftp_client.put(localFilePath, remoteFilePath)
except FileNotFoundError as err:
print(f"File {localFilePath} was not found on the local system")
sftp_client.close()


def executeCommand(self, command):
stdin,stdout,stderr= self.__SSH_Client.exec_command(command)
print(stdout.readlines())
print(stderr.readlines())
Photo by Mohd Arman on Unsplash

If you like the tutorial, please follow and clap 👏.
Please comment for any doubts or tutorial on any other topic.

Happy Coding, Lets meet on another tutorial. Howzzzzz the Joshhhhhhhh …???… ⭐🤩🔥

--

--

KIHSA Rai
Nerd For Tech

I'm a Software Engineer experienced in web tech (ReactJS, TypeScript, GraphQL), Payment, RPA, C++, Python, Android, AWS. I'm always learning and improving.