Using Python's FTP library to retrieve files
this is my first post on here so I'm happy to be a part of the community. I have a fairly mundane question to ask, but it's been a fairly annoying problem so I'm hoping to find answers.
So I'm trying to use Python's FTPLIB module to retrieve a binary file.
The code entered directly into the interpreter looked like this:
>>> from ftplib import FTP
>>> ftp = FTP('xxx.xx.xx.x') # IP of target device
>>> ftp.login()
>>> file = "foobar.xyz" # target file
>>> ftp.retrbinary("RETR " + file, open('filez.txt', 'wb').write)
While certain functions are working (I can view all files on the device, get the welcome message from the FTP server application, and even rename files), when I try to execute the last command above, I get
error_perm Traceback (most recent call last)
/Users/user_name/<ipython console> in <module>()
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in retrlines(self, cmd, callback)
419 if callback is None: callback = print_line
420 resp = self.sendcmd('TYPE A')
--> 421 conn = self.transfercmd(cmd)
422 fp = conn.makefile('rb')
423 while 1:
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in transfercmd(self, cmd, rest)
358 def transfercmd(self, cmd, rest=None):
359 """Like ntransfercmd() but returns only the socket."""
--> 360 return self.ntransfercmd(cmd, rest)[0]
361
362 def login(self, user = '', passwd = '', acct = ''):
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in ntransfercmd(self, cmd, rest)
327 if rest is not None:
328 self.sendcmd("REST %s" % rest)
--> 329 resp = self.sendcmd(cmd)
330 # Some servers apparently send a 200 reply to
331 # a LIST or STOR command, before the 150 reply
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in sendcmd(self, cmd)
241 '''Send a command and return the response.'''
242 self.putcmd(cmd)
--> 243 return self.getresp()
244
245 def voidcmd(self, cmd):
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/ftplib.pyc in getresp(self)
216 raise error_temp, resp
217 if c == '5':
--> 218 raise error_perm, resp
219 raise error_proto, resp
220
error_perm: 502 Command not implemented.
I've looked through the ftplib source but my programming experience with these sorts of task is pretty limited, as I normally use Pyth开发者_运维百科on for math and haven't had to work with FTP before.
So, if anyone could give me some ideas on a solution, that would be a huge help. Alternatively, if you could suggest another solution path in a different language that would be equally helpful.
It looks like you are logging-in anonymously (no username/password specified in ftp.login()
) thus you get permission error. Try logging-in with
ftp.login(user='foo', passwd='bar')
instead.
Edit: here is a short example of ftplib usage (simplistic, without error handling):
#!/usr/bin/env python
from ftplib import FTP
HOST = "localhost"
UNAME = "foo"
PASSWD = "bar"
DIR = "pub"
FILE = "test.test"
def download_cb(block):
file.write(block)
ftp = FTP(HOST)
ftp.login(user=UNAME, passwd=PASSWD)
ftp.cwd(DIR)
file = open(FILE, "wb")
ftp.retrbinary("RETR " + FILE, download_cb)
file.close()
ftp.close()
Note: In case retrbinary
doesn't work, you can also try setting binary mode explicitly with ftp.sendcmd("TYPE I")
before calling it. This is non-typical case, however may help with some exotic ftp servers.
If your case is really that simple, there's no need to use the ftplib modlue. urllib.urlretrieve
will do what you need. E.g.:
import urllib
urllib.urlretrieve('ftp://xxx.xx.xx.x/foobar.xyz', filename='filez.txt')
Note: this would be urllib.request.urlretrieve
in python 3.x, by the way...
And if the ftp server isn't anonymous, you just specify the username and password in the url string as you normally would (e.g. ftp://user:password@server/path/to/file
). Of course, the ftp protocol sends the password in plain text, and you've stored the username and password in the script, so this is insecure for multiple reasons, but that's true regardless of which library you use.
Works fine for me, try with other server (i've tested with a debian ftp server.):
ftp = FTP('xx.xx.xx.xx')'
ftp.login()
'230 Login successful.'
file="robots.txt"
ftp.retrlines("RETR "+file, open('filez.txt', 'wb').write)
'226 File send OK.'
精彩评论