上午 8:51:19 收到此错误 |痕迹 @8F596749-638656982249418103 下载或归档文件时出错:EOF o...rred 违反协议(_ssl.c:2706),当我向 az 函数发送请求时,我使用基于 tls 加密的显式 ftp,这是我的代码: import azure.functions as功能
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")
上午 8:51:19 收到此错误 |痕迹 @8F596749-638656982249418103 下载或存档文件时出错:EOF o...rred 违反协议 (_ssl.c:2706),当我向 az 函数发送请求时,我使用基于 tls 加密的显式 ftp,
下载或归档文件时出错:EOF 发生违反协议:-
根据Microsoft Q&A,SSL连接突然关闭时会出现EOF错误协议问题,可能是网络端问题或服务器端问题。请检查以下内容以解决问题。
首先,你可以尝试升级python相关的包,同时检查是否已经安装了最新的python并与系统兼容
此外,有时问题可能是由于套接字需要自动包装 ssl,因为存在隐式 FTPS 连接。请参阅 @hynekcer 的 SO 以获取类似信息。
如Python套接字连接文档中所述,您可以尝试将SSL上下文设置为
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
专门为客户端连接而存在,可能有助于避免此处的冲突。
try:
# Create a context that doesn't verify certificates
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
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
另请检查
portal >> function app
出站安全规则虚拟网络是否允许流向 FTP 服务器(TCP 端口 21)的流量。