[英]"ftplib.error_perm: 550 Operation not permitted" when trying to download the second file from the same directory using FTP_TLS
Got this error while running my script: ftplib.error_perm: 550 Operation not permitted
运行我的脚本时出现此错误:
ftplib.error_perm: 550 Operation not permitted
ftpdownloader.py: ftpdownloader.py:
import ftplib
import threading
import logging
import os
class Client:
def __init__(self, host, port, username, passwd):
self.host = host
self.port = port
self.username = username
self.passwd = passwd
self.ftp = None
self.set_ftp()
self.login_to_ftp()
def set_ftp(self):
self.ftp = ftplib.FTP_TLS(self.host)
self.ftp.set_debuglevel(True)
self.ftp.set_pasv(True)
def login_to_ftp(self):
self.ftp.login(self.username, self.passwd)
self.ftp.prot_p()
def download_file(self, filename, local_filename=None):
logging.info('Will download this file : "%s"', filename)
if local_filename is None:
local_filename = filename
self.ftp.voidcmd('TYPE I')
sock = self.ftp.transfercmd('RETR ' + filename)
def background():
with open(local_filename, 'wb') as f:
while True:
block = sock.recv(1024 * 1024)
if not block:
break
f.write(block)
logging.debug('will close sock ...')
sock.close()
t = threading.Thread(target=background)
t.start()
while t.is_alive():
t.join(20)
self.ftp.voidcmd('NOOP')
# self.ftp.close()
logging.info("File downloaded with success : %s", local_filename)
def get_directories_list(self, directory_path):
logging.debug('Getting directories of directory : %s', directory_path)
directories_list = []
for elem in self.ftp.mlsd(directory_path):
if elem[1]['type'] == 'dir':
directories_list += [elem[0]]
return directories_list
def get_files_list(self, directory_path):
logging.debug('Getting files of directory : %s', directory_path)
files_list = []
for elem in self.ftp.mlsd(directory_path):
if elem[1]['type'] == 'file':
files_list += [elem[0]]
return files_list
def get_all_files_of_directory(self, ftp_directory_root, ftp_directory_path, output_directory_path):
current_position = ftp_directory_root + ftp_directory_path
current_output_directory = output_directory_path + ftp_directory_path
# self.set_ftp()
# self.login_to_ftp()
files_list = self.get_files_list(current_position)
directories_list = self.get_directories_list(current_position)
os.makedirs(current_output_directory, exist_ok=True)
for file in files_list:
self.download_file(current_position + '/' + file, current_output_directory + '/' + file)
# self.set_ftp()
# self.login_to_ftp()
for directory in directories_list:
if ftp_directory_path == '/':
ftp_directory_path = ''
self.get_all_files_of_directory(ftp_directory_root, ftp_directory_path + '/' + directory,
output_directory_path)
Test script:测试脚本:
test.py:测试.py:
from ftpdownloader import Client
ftp_host_name = 'ftp-hostname'
ftp_port = 21
ftp_username = 'username'
ftp_password = '*******'
client = Client(ftp_host_name, ftp_port, ftp_username, ftp_password)
client.get_all_files_of_directory('/directory1', '/', 'downloads/test')
FTP content: FTP 内容:
- directory1:
- directory11:
- file111.xml
- file112.zip
- directory12:
- file121.xml
- file122.zip
When I run my test.py script (with commented lines on ftpdownloader.py), the script:当我运行我的 test.py 脚本(在 ftpdownloader.py 上带有注释行)时,脚本:
ftplib.error_perm: 550 Operation not permitted
ftplib.error_perm: 550 Operation not permitted
FTP_TLS debug logs: FTP_TLS 调试日志:
*cmd* 'TYPE A'
*resp* '200 Type set to A'
*cmd* 'PASV'
*resp* '227 Entering Passive Mode (81,252,220,78,234,106).'
*cmd* 'MLSD /directory1'
*resp* '150 Opening ASCII mode data connection for MLSD'
*resp* '226 Transfer complete'
*cmd* 'TYPE A'
*resp* '200 Type set to A'
*cmd* 'PASV'
*resp* '227 Entering Passive Mode (81,252,220,78,234,187).'
*cmd* 'MLSD /directory1'
*resp* '150 Opening ASCII mode data connection for MLSD'
*resp* '226 Transfer complete'
*cmd* 'TYPE A'
*resp* '200 Type set to A'
*cmd* 'PASV'
*resp* '227 Entering Passive Mode (81,252,220,78,234,99).'
*cmd* 'MLSD /directory1/directory11'
*resp* '150 Opening ASCII mode data connection for MLSD'
*resp* '226 Transfer complete'
*cmd* 'TYPE A'
*resp* '200 Type set to A'
*cmd* 'PASV'
*resp* '227 Entering Passive Mode (81,252,220,78,234,131).'
*cmd* 'MLSD /directory1/directory11'
*resp* '150 Opening ASCII mode data connection for MLSD'
*resp* '226 Transfer complete'
*cmd* 'TYPE I'
*resp* '200 Type set to I'
*cmd* 'PASV'
*resp* '227 Entering Passive Mode (81,252,220,78,234,126).'
*cmd* 'RETR /directory1/directory11/file111.xml'
*resp* '150 Opening BINARY mode data connection for /directory1/directory11/file111.xml (879 bytes)'
*cmd* 'NOOP'
*resp* '226 Transfer complete'
*cmd* 'TYPE I'
*resp* '550 Operation not permitted'
Traceback (most recent call last):
File "..../envs/back/lib/python3.9/code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 11, in <module>
File "..../back/tools/ftpdownload.py", line 86, in get_all_files_of_directory
self.get_all_files_of_directory(ftp_directory_root, ftp_directory_path + '/' + directory,
File "..../back/tools/ftpdownload.py", line 86, in get_all_files_of_directory
self.get_all_files_of_directory(ftp_directory_root, ftp_directory_path + '/' + directory,
File "..../back/tools/ftpdownload.py", line 79, in get_all_files_of_directory
self.download_file(current_position + '/' + file, current_output_directory + '/' + file)
File "..../back/tools/ftpdownload.py", line 30, in download_file
self.ftp.voidcmd('TYPE I')
File ".../envs/back/lib/python3.9/ftplib.py", line 286, in voidcmd
return self.voidresp()
File "..../envs/back/lib/python3.9/ftplib.py", line 259, in voidresp
resp = self.getresp()
File "..../envs/back/lib/python3.9/ftplib.py", line 254, in getresp
raise error_perm(resp)
ftplib.error_perm: 550 Operation not permitted
So, I tried to run the script using login after downloading each file (uncomment lines for ftpdownloader.py script)!因此,我尝试在下载每个文件后使用 login 运行脚本(取消 ftpdownloader.py 脚本的注释行)! It's work but It's too slow comparing FileZilla or other FTP client!
它可以工作,但比较 FileZilla 或其他 FTP 客户端太慢了!
Can you help please?你能帮忙吗?
There are at least two problems imo: imo至少有两个问题:
RETR
.RETR
的回复。 I believe this is what is happening:我相信这是正在发生的事情:
RETR
and start the transfer.RETR
并开始传输。NOOP
and wait for a response.NOOP
并等待响应。NOOP
, until RETR
completes.NOOP
,直到RETR
完成。226
to the RETR
.226
响应RETR
。226
as a response to NOOP
226
误解为对NOOP
的响应550
as a response to NOOP
(but that's just a guess)550
作为对NOOP
的响应(但这只是猜测)RETR
(If it did, you will notice the mismatch between responses and answers at the first file already)RETR
的响应(如果确实如此,您会注意到第一个文件中的响应和答案之间的不匹配)TYPE
command for the second fileTYPE
命令550
to RETR
and misinterpret it as a response to TYPE
.RETR
的排队响应550
并将其误解为对TYPE
的响应。 I do not think the answer you have based your code on is correct.我不认为您基于代码的答案是正确的。 It indeed cannot handle more than one file, as it breaks pairing of requests and responses.
它确实不能处理多个文件,因为它破坏了请求和响应的配对。 If you believe the
NOOP
solves the freeze, then the correct solution might be to just send the NOOP
command without waiting for a response using FTP.sendcmd
:如果您认为
NOOP
解决了冻结问题,那么正确的解决方案可能是使用FTP.sendcmd
发送NOOP
命令而不等待响应:
ftp.sendcmd('NOOP')
noops_sent += 1
And then at the end of the the transfer, you have to wait for the RETR
response using FTP.voidresp
(see the code of FTP.retrbinary
) and then wait for responses of all queued NOOP
commands:然后在传输结束时,您必须使用
FTP.voidresp
等待RETR
响应(参见 FTP.retrbinary 的FTP.retrbinary
),然后等待所有排队的NOOP
命令的响应:
ftp.voidresp()
for _ in range(noops_sent):
ftp.voidresp()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.