使用boto3和ftplib将FTP文件传至S3时出现500语法错误如何解决
报错根因&修复方案
1. 500语法错误直接原因
ftplib的retrbinary()方法要求第一个参数必须是完整的FTP RETR命令,格式为RETR 文件名,你直接传入纯文件名作为参数,FTP服务端无法识别非法命令,因此抛出500语法错误。
2. 隐含的S3上传错误
你将retrbinary()的返回值赋值给buffer并传给S3的put方法属于逻辑错误:retrbinary()的返回值是FTP响应的状态字符串,不是文件内容。实际你拉取的文件数据已经全部写入了你创建的io.BytesIO对象myfile中,直接传myfile作为Body即可。
修正后可运行代码
import ftplib import io import boto3 # 自行替换为你的实际参数值 ipaddr = "你的FTP地址" usr = "FTP用户名" pswd = "FTP密码" folder = "FTP目标目录" filename = "要传输的文件名" bucket_name = "S3存储桶名" # 初始化S3资源 s3_resource = boto3.resource('s3') ftp = ftplib.FTP(ipaddr) ftp.login(usr, pswd) ftp.cwd(folder) myfile = io.BytesIO() # 修正RETR命令格式,加前缀拼接文件名 ftp.retrbinary(f'RETR {filename}', myfile.write) # 移动文件指针到起始位置 myfile.seek(0) # 直接传入BytesIO对象作为上传体 s3_resource.Object(bucket_name, f"{folder}/{filename}").put(Body=myfile) ftp.quit()
注意事项
如果待传输的文件名包含空格、特殊符号,需要将文件名用双引号包裹避免命令解析错误,写法调整为:
ftp.retrbinary(f'RETR "{filename}"', myfile.write)
如果需要处理超大文件避免内存占用过高,可以改用流式分段上传,在retrbinary的回调函数中直接向S3上传分片即可。
内容的提问来源于stack exchange,提问作者Dimas Aps
相关产品推荐
相关产品推荐

