Skip to content

Commit f4fcd14

Browse files
Merge pull request #26 from vinod-kanigicherla/add-ftp-tasks
Added FTP tasks
2 parents f988444 + 5626c40 commit f4fcd14

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed

tasks/upload/ftp.py

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import os
2+
from ftplib import FTP, error_perm
3+
4+
from netunicorn.base import Failure, Result, Success, Task
5+
6+
7+
class UploadToFTP(Task):
8+
"""
9+
Task for uploading a local file to an FTP Server. Establishes a connection to the specified FTP server, navigates to the desired remote directory, and uploads the specified local file.
10+
"""
11+
12+
def __init__(
13+
self,
14+
local_filepath: str,
15+
ftp_url: str,
16+
username: str,
17+
password: str,
18+
destination_dir: str = "/",
19+
timeout: int = 30,
20+
*args,
21+
**kwargs,
22+
):
23+
"""
24+
Initializes the UploadToFTP task with parameters.
25+
26+
Parameters:
27+
local_filepath (str): Path to local file to upload.
28+
ftp_url (str): URL or IP address of FTP.
29+
username (str): Username credential for FTP auth.
30+
password (str): Password credential for FTP auth.
31+
destination_dir (str): Destination directory on the FTP server where the file will be uploaded to. Defaults to "/".
32+
timeout (int, optional): Timeout value for FTP connection measued in seconds. Defaults to 30 seconds.
33+
"""
34+
super().__init__(*args, **kwargs)
35+
self.local_filepath = local_filepath
36+
self.ftp_url = ftp_url
37+
self.username = username
38+
self.password = password
39+
self.destination_dir = destination_dir
40+
self.timeout = timeout
41+
42+
def run(self) -> Result:
43+
"""
44+
Uploads the local file to FTP server.
45+
46+
Steps:
47+
1. Finds the specified local file.
48+
2. Connects to FTP server using provided credentials.
49+
3. Sets remote directory if specified, else defaults to "/".
50+
4. Uploads the local file to FTP server and closes connection.
51+
52+
Returns:
53+
Result:
54+
Success: Contains a success message if successful upload.
55+
--OR--
56+
Failure: Contains an error message if upload fails.
57+
58+
"""
59+
try:
60+
if not os.path.isfile(self.local_filepath):
61+
return Failure(f"Local file does not exist: {self.local_filepath}")
62+
63+
ftp = FTP(self.ftp_url, timeout=self.timeout) # Modify timeout as needed
64+
ftp.login(user=self.username, passwd=self.password)
65+
66+
if self.destination_dir:
67+
ftp.cwd(self.destination_dir)
68+
69+
with open(self.local_filepath, "rb") as f:
70+
remote_filename = os.path.basename(self.local_filepath)
71+
ftp.storbinary(f"STOR {remote_filename}", f)
72+
73+
ftp.quit()
74+
return Success(
75+
f"Successfully uploaded {self.local_filepath} to {self.ftp_url}/{self.destination_dir}"
76+
)
77+
78+
except FileNotFoundError:
79+
return Failure(f"File not found: {self.local_filepath}")
80+
81+
except error_perm as e:
82+
return Failure(f"FTP permission error: {e}")
83+
84+
except Exception as e:
85+
return Failure(f"An unexpected error occurred: {str(e)}")
86+
87+
88+
class RetrieveFromFTP(Task):
89+
"""
90+
Task for retrieving a file from an FTP server to a local directory. Establishes a connection to the specified FTP server, navigates to the desired remote directory and downloads the specified file to a local directory.
91+
"""
92+
93+
def __init__(
94+
self,
95+
ftp_remote_filepath: str,
96+
ftp_url: str,
97+
username: str,
98+
password: str,
99+
local_dir: str = "./",
100+
timeout: int = 30,
101+
*args,
102+
**kwargs,
103+
):
104+
"""
105+
Initializes the RetrieveFromFTP task with parameters.
106+
107+
Parameters:
108+
ftp_remote_filepath (str): Full path of the file on the FTP server to retrieve.
109+
ftp_url (str): URL or IP address of the FTP server.
110+
username (str): Username for FTP authentication.
111+
password (str): Password for FTP authentication.
112+
local_dir (str, optional): Local directory to save the retrieved file. Defaults to "./".
113+
timeout (int, optional): Timeout value for FTP connection measued in seconds. Defaults to 30 seconds.
114+
*args: Variable length argument list.
115+
**kwargs: Arbitrary keyword arguments.
116+
"""
117+
super().__init__(*args, **kwargs)
118+
self.ftp_remote_filepath = ftp_remote_filepath
119+
self.ftp_url = ftp_url
120+
self.username = username
121+
self.password = password
122+
self.local_dir = local_dir
123+
self.timeout = timeout
124+
125+
def run(self) -> Result:
126+
"""
127+
Run the FTP file retrieval process.
128+
129+
Steps:
130+
1. Connects to FTP server using provided credentials.
131+
2. Navigates to the directory containing the target file.
132+
3. Downloads the specified file to the local directory. Defaults to "./".
133+
134+
Returns:
135+
Result:
136+
Success: Contain success message upon successful download.
137+
--OR--
138+
Failure: Contains an error message if the download fails.
139+
140+
"""
141+
try:
142+
if not os.path.isdir(self.local_dir):
143+
os.makedirs(self.local_dir, exist_ok=True)
144+
145+
ftp = FTP(self.ftp_url, timeout=self.timeout) # Modify timeout as needed
146+
ftp.login(user=self.username, passwd=self.password)
147+
148+
remote_dir, remote_filename = os.path.split(self.ftp_remote_filepath)
149+
if remote_dir:
150+
ftp.cwd(remote_dir)
151+
152+
local_filepath = os.path.join(self.local_dir, remote_filename)
153+
with open(local_filepath, "wb") as f:
154+
ftp.retrbinary(f"RETR {remote_filename}", f.write)
155+
156+
ftp.quit()
157+
158+
return Success(
159+
f"Successfully downloaded {self.ftp_remote_filepath} to {local_filepath}"
160+
)
161+
162+
except FileNotFoundError:
163+
return Failure(f"File not found: {self.ftp_remote_filepath}")
164+
165+
except error_perm as e:
166+
return Failure(f"FTP permission error: {e}")
167+
168+
except Exception as e:
169+
return Failure(f"An unexpected error occurred: {str(e)}")

0 commit comments

Comments
 (0)