am getting this error 8:51:19 AM | Trace @8F596749-638656982249418103 Error downloading or archiving file: EOF o...rred in violation of protocol (_ssl.c:2706), when am sending request to the az function am using explicit ftp over tls encryption, this is my code: import azure.functions as func
import ftplib
import json
import base64
import io
import ssl
def main(req: func.HttpRequest) -> func.HttpResponse:
try:
params = req.get_json()
host = params.get('host')
port = params.get('port', 21)
username = params.get('username')
password = params.get('password')
remote_dir = params.get('remote_dir')
action = params.get('action', 'list')
filename = params.get('filename')
file_content = params.get('file_content')
archive = params.get('archive', 'no')
print(f"Received request: Action={action}, Host={host}, Port={port}, Username={username}, Remote Dir={remote_dir}, Archive={archive}")
if action == 'list':
files = list_ftp_files(host, port, username, password, remote_dir)
if files:
print(f"Successfully listed {len(files)} files")
return func.HttpResponse(json.dumps({"success": True, "files": files}), mimetype="application/json")
else:
print("Failed to retrieve files")
return func.HttpResponse(json.dumps({"success": False, "error": "Failed to retrieve files"}), mimetype="application/json")
elif action == 'download':
if not filename:
print("Download requested but filename not provided")
return func.HttpResponse(json.dumps({"success": False, "error": "Filename not provided"}), mimetype="application/json")
print(f"Attempting to download file: {filename}")
try:
file_content, archived = download_ftp_file(host, port, username, password, remote_dir, filename, archive.lower() == 'yes')
if file_content:
encoded_content = base64.b64encode(file_content).decode('utf-8')
print(f"Successfully downloaded file: {filename}, Size: {len(file_content)} bytes, Archived: {archived}")
return func.HttpResponse(json.dumps({
"success": True,
"filename": filename,
"content": encoded_content,
"size": len(file_content),
"archived": archived
}), mimetype="application/json")
else:
print(f"Failed to download file: {filename}")
return func.HttpResponse(json.dumps({"success": False, "error": f"Failed to download file {filename}"}), mimetype="application/json")
except Exception as e:
print(f"Error during file download: {str(e)}")
return func.HttpResponse(json.dumps({"success": False, "error": f"Error downloading file {filename}: {str(e)}"}), mimetype="application/json")
elif action == 'upload':
if not filename or not file_content:
print("Upload requested but filename or file content not provided")
return func.HttpResponse(json.dumps({"success": False, "error": "Filename and file content are required for upload"}), mimetype="application/json")
print(f"Attempting to upload file: {filename}")
try:
success = upload_ftp_file(host, port, username, password, remote_dir, filename, file_content)
if success:
print(f"Successfully uploaded file: {filename}")
return func.HttpResponse(json.dumps({"success": True, "message": f"File {filename} uploaded successfully"}), mimetype="application/json")
else:
print(f"Failed to upload file: {filename}")
return func.HttpResponse(json.dumps({"success": False, "error": f"Failed to upload file {filename}"}), mimetype="application/json")
except Exception as e:
print(f"Error during file upload: {str(e)}")
return func.HttpResponse(json.dumps({"success": False, "error": f"Error uploading file {filename}: {str(e)}"}), mimetype="application/json")
else:
print(f"Invalid action requested: {action}")
return func.HttpResponse(json.dumps({"success": False, "error": "Invalid action"}), mimetype="application/json")
except Exception as e:
print(f"Unexpected error in main function: {str(e)}")
return func.HttpResponse(json.dumps({"success": False, "error": f"An unexpected error occurred: {str(e)}"}), mimetype="application/json")
def connect_ftp(host, port, username, password):
try:
# Create a context that doesn't verify certificates
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
# Establishing a secure FTP_TLS connection with custom SSL context
ftp = ftplib.FTP_TLS()
ftp.context = context # Assign the modified context to FTP_TLS
ftp.connect(host, port, timeout=60)
ftp.login(username, password)
ftp.prot_p() # Enable data connection encryption
ftp.set_pasv(True) # Use passive mode for secure connections
return ftp
except Exception as e:
print(f"FTP connection error: {e}")
return None
def list_ftp_files(host, port, username, password, remote_dir):
ftp = connect_ftp(host, port, username, password)
if not ftp:
print("Failed to establish FTP connection")
return None
try:
print(f"Changing to directory: {remote_dir}")
ftp.cwd(remote_dir)
print("Successfully changed directory")
print("Listing files...")
files = ftp.nlst()
print(f"Files retrieved: {files}")
return files
except Exception as e:
print(f"Error listing files: {str(e)}")
finally:
if ftp:
try:
ftp.quit()
print("FTP connection closed")
except:
print("Error closing FTP connection")
return None
def download_ftp_file(host, port, username, password, remote_dir, filename, archive):
ftp = connect_ftp(host, port, username, password)
if not ftp:
print("Failed to establish FTP connection for download")
return None, False
try:
print(f"Changing to directory: {remote_dir}")
ftp.cwd(remote_dir)
print("Successfully changed directory")
print(f"Initiating download of {filename}")
file_content = io.BytesIO()
ftp.retrbinary(f"RETR {filename}", file_content.write)
print(f"Download completed. File size: {len(file_content.getvalue())} bytes")
archived = False
if archive:
archive_dir = "Archive"
try:
ftp.cwd(archive_dir)
except ftplib.error_perm:
ftp.mkd(archive_dir)
ftp.cwd('..')
print(f"Moving file to Archive: {filename}")
ftp.rename(filename, f"{archive_dir}/{filename}")
print(f"File {filename} moved to Archive successfully")
archived = True
return file_content.getvalue(), archived
except Exception as e:
print(f"Error downloading or archiving file: {str(e)}")
raise
finally:
if ftp:
try:
ftp.quit()
print("FTP connection closed")
except:
print("Error closing FTP connection")
def upload_ftp_file(host, port, username, password, remote_dir, filename, file_content):
ftp = connect_ftp(host, port, username, password)
if not ftp:
print("Failed to establish FTP connection for upload")
return False
try:
print(f"Changing to directory: {remote_dir}")
ftp.cwd(remote_dir)
print("Successfully changed directory")
print(f"Initiating upload of {filename}")
ftp.storbinary(f"STOR {filename}", io.BytesIO(base64.b64decode(file_content)))
print(f"Upload completed.")
return True
except Exception as e:
print(f"Error uploading file: {str(e)}")
raise
finally:
if ftp:
try:
ftp.quit()
print("FTP connection closed")
except:
print("Error closing FTP connection")
am getting this error 8:51:19 AM | Trace @8F596749-638656982249418103 Error downloading or archiving file: EOF o...rred in violation of protocol (_ssl.c:2706), when am sending request to the az function am using explicit ftp over tls encryption,