Paramiko- How to transfer files with Remote System (SFTP Servers) using Python
A comprehensive guide on how to upload and download files from an SFTP-Server/remote machine using paramiko
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.
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
)
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 directory
is 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")
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())
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 …???… ⭐🤩🔥
Read my other articles
- Mqttx Client with AWS Mqtt Broker | by KIHSA Rai | Dec, 2023 | Medium
- Python ConfigParser: A Comprehensive Guide ⚙️ | by KIHSA Rai | Nerd For Tech | Medium
- Everything to know about MQTT (Message Queue Telemetry Transport) | by KIHSA Rai | Oct, 2023 | Medium
- Python Profiling: Know Why and Where Your Code is Slow | by KIHSA Rai | Sep, 2023 | Medium