pip install ftplib

Python中默认安装的ftplib模块定义了FTP类,其中函数有限,可用来实现简单的ftp客户端,用于上传或下载文件,函数列举如下

ftp登陆连接
from ftplib import FTP #加载ftp模块
ftp=FTP() #设置变量
ftp.set_debuglevel(2) #打开调试级别2,显示详细信息
ftp.connect("IP","port") #连接的ftp sever和端口
ftp.login("user","password") #连接的用户名,密码
print ftp.getwelcome() #打印出欢迎信息
ftp.cmd("xxx/xxx") #进入远程目录
bufsize=``1024` #设置的缓冲区大小
filename=``”filename.txt”` #需要下载的文件
file_handel=open(filename,"wb").write #以写模式在本地打开文件
ftp.retrbinary("RETR filename.txt",file_handle,bufsize) #接收服务器上文件并写入本地文件
ftp.set_debuglevel(0) #关闭调试模式
ftp.quit() #退出ftp
ftp相关命令操作
ftp.cwd(pathname) #设置FTP当前操作的路径
ftp.dir() #显示目录下所有目录信息
ftp.nlst() #获取目录下的文件
ftp.mkd(pathname) #新建远程目录
ftp.pwd() #返回当前所在位置
ftp.rmd(dirname) #删除远程目录
ftp.delete(filename) #删除远程文件
ftp.rename(fromname, toname) #将fromname修改名称为toname。
ftp.storbinaly("STOR filename.txt",file_handel,bufsize) #上传目标文件
ftp.retrbinary("RETR filename.txt",file_handel,bufsize) #下载FTP文件

FTP.quit()与FTP.close()的区别

  • FTP.quit():发送QUIT命令给服务器并关闭掉连接。这是一个比较“缓和”的关闭连接方式,但是如果服务器对QUIT命令返回错误时,会抛出异常。
  • FTP.close():单方面的关闭掉连接,不应该用在已经关闭的连接之后,例如不应用在FTP.quit()之后。

下载、上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#coding: utf-8
from ftplib import FTP
import time
import tarfile
#!/usr/bin/python
#-*- coding: utf-8 -*-

from ftplib import FTP

def ftpconnect(host, username, password):
ftp = FTP()
#ftp.set_debuglevel(2) #打开调试级别2,显示详细信息
ftp.connect(host, 21) #连接
ftp.login(username, password) #登录,如果匿名登录则用空串代替即可
return ftp

def downloadfile(ftp, remotepath, localpath):
bufsize = 1024 #设置缓冲块大小
fp = open(localpath,'wb') #以写模式在本地打开文件
ftp.retrbinary('RETR ' + remotepath, fp.write, bufsize) #接收服务器上文件并写入本地文件
ftp.set_debuglevel(0) #关闭调试
fp.close() #关闭文件

def uploadfile(ftp, remotepath, localpath):
bufsize = 1024
fp = open(localpath, 'rb')
ftp.storbinary('STOR '+ remotepath , fp, bufsize) #上传文件
ftp.set_debuglevel(0)
fp.close()

if __name__ == "__main__":
ftp = ftpconnect("******", "***", "***")
downloadfile(ftp, "***", "***")
uploadfile(ftp, "***", "***")

ftp.quit()

上传、下载文件/目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#coding:utf-8
from ctypes import *
import os
import sys
import ftplib

class myFtp:
ftp = ftplib.FTP()
bIsDir = False
path = ""
def __init__(self, host, port='21'):
#self.ftp.set_debuglevel(2) #打开调试级别2,显示详细信息
#self.ftp.set_pasv(0) #0主动模式 1 #被动模式
self.ftp.connect( host, port )

def Login(self, user, passwd):
self.ftp.login( user, passwd )
print self.ftp.welcome

def DownLoadFile(self, LocalFile, RemoteFile):
file_handler = open( LocalFile, 'wb' )
self.ftp.retrbinary( "RETR %s" %( RemoteFile ), file_handler.write )
file_handler.close()
return True

def UpLoadFile(self, LocalFile, RemoteFile):
if os.path.isfile( LocalFile ) == False:
return False
file_handler = open(LocalFile, "rb")
self.ftp.storbinary('STOR %s'%RemoteFile, file_handler, 4096)
file_handler.close()
return True

def UpLoadFileTree(self, LocalDir, RemoteDir):
if os.path.isdir(LocalDir) == False:
return False
print "LocalDir:", LocalDir
LocalNames = os.listdir(LocalDir)
print "list:", LocalNames
print RemoteDir
self.ftp.cwd( RemoteDir )
for Local in LocalNames:
src = os.path.join( LocalDir, Local)
if os.path.isdir( src ): self.UpLoadFileTree( src, Local )
else:
self.UpLoadFile( src, Local )

self.ftp.cwd( ".." )
return

def DownLoadFileTree(self, LocalDir, RemoteDir):
print "remoteDir:", RemoteDir
if os.path.isdir( LocalDir ) == False:
os.makedirs( LocalDir )
self.ftp.cwd( RemoteDir )
RemoteNames = self.ftp.nlst()
print "RemoteNames", RemoteNames
print self.ftp.nlst("/del1")
for file in RemoteNames:
Local = os.path.join( LocalDir, file )
if self.isDir( file ):
self.DownLoadFileTree( Local, file )
else:
self.DownLoadFile( Local, file )
self.ftp.cwd( ".." )
return

def show(self, list):
result = list.lower().split( " " )
if self.path in result and "<dir>" in result:
self.bIsDir = True

def isDir(self, path):
self.bIsDir = False
self.path = path
#this ues callback function ,that will change bIsDir value
self.ftp.retrlines( 'LIST', self.show )
return self.bIsDir

def close(self):
self.ftp.quit()

if __name__ == "__main__":
ftp = myFtp('*****')
ftp.Login('***','***')

ftp.DownLoadFileTree('del', '/del1')#ok
ftp.UpLoadFileTree('del', "/del1" )
ftp.close()
print "ok!"

异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#coding: utf-8
#from ftplib import FTP
import ftplib
import socket
import os

def ftpconnect(ftp_info):
try:
ftp = ftplib.FTP(ftp_info[0])
except (socket.error, socket.gaierror):
print "ERROR: cannot reach %s" % ftp_info[0]
return None

username = ftp_info[1]
passwd = ftp_info[2]
try:
ftp.login(username, passwd)
except ftplib.error_perm:
print "ERROR: cannot login anonymously"
ftp.quit()
return None
return ftp

if __name__ == "__main__":
info_list = ["10.19.3.199", "fastupdate_amap", "@utonavi&A.map"]
ftp = ftpconnect(info_list)
if not ftp:
exit(1)
bufsize = 1024
fname = "20150416113942674.tar.gz"
fp = open(os.path.join(".", fname), 'wb')
remotefile = os.path.join("/ADF++", fname)
ftp.retrbinary("RETR " + remotefile, fp.write, bufsize)

#是否有目录,没有就创建;有的话看是否有权限创建
a = ftp.dir()
try:
ftp.cwd("jimi")
except ftplib.error_perm:
try:
ftp.mkd("jimi")
except ftplib.error_perm:
print "WARNING: U have no authority to make dir"
finally:
ftp.quit()

Windows命令

1.系统环境

  FTP客户端:Windows7旗舰版,管理员权限命令行;

  FTP服务端:CentOS 6.5,VSFTP,端口 21(默认)

2.登陆FTP

  1. 在命令行下输入 ftp,出现 ftp>即进入FTP命令行
  2. open FTP的IP地址/域名 例如 open 169.254.234.241 (当然有最简单的方式 直接在命令行下 ftp FTP的IP地址/域名)
  3. 按照提示输入用户名和密码,完成登陆
1
2
3
4
5
6
7
8
9
10
11
12
Microsoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。

C:\Users\Administrator>ftp
ftp> open 169.254.234.241
连接到 169.254.234.241。
220 Welcome to blah FTP service.
用户(169.254.234.241:(none)): wy
331 Please specify the password.
密码:
230 Login successful.
ftp>

3.上传一个文件

  1. put(或者 send,上传多个使用 mput) 文件名(包含路径) 例如 put C:\Users\Administrator\Documents\Myself.pub
  2. ls(或者 dir) 查看当前目录文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ftp> put C:\Users\Administrator\Documents\Myself.pub
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
ftp: 发送 233 字节,用时 0.02秒 14.56千字节/秒。
ftp> send C:\Users\Administrator\Documents\Myself
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 Transfer complete.
ftp: 发送 1004 字节,用时 0.00秒 1004000.00千字节/秒
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
Myself
Myself.pub
226 Directory send OK.
ftp: 收到 20 字节,用时 0.00秒 20.00千字节/秒。
ftp>

  很显然,send 的速度比 put 快不少。但是他们两个的区别我没有详细的查。

4.下载一个文件

  1. lcd 本地目录路径 设置当前工作路径,也就是你要把文件下载到哪。默认是在当前使用命令行的用户的主目录。我的是 C:\Users\Administrator。也可以使用 !chdir 查看当前目录。
  2. cd 服务器目录 进入到你要下载的文件在服务器端的目录位置
  3. get(下载多个用 mget) 文件名 下载该文件。例如 get Myself
  4. !dir 查看当前目录文件,就能看到你刚才下载的文件啦
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r-- 1 500 500 986 Dec 03 10:08 Myself
-rw-r--r-- 1 500 500 233 Dec 03 10:07 Myself.pub
226 Directory send OK.
ftp: 收到 132 字节,用时 0.00秒 132000.00千字节/秒。
ftp> !cd C:\Users\Administrator\Desktop
ftp> !chdir
C:\Users\Administrator
ftp> lcd C:\Users\Administrator\Desktop
目前的本地目录 C:\Users\Administrator\Desktop。
ftp> !chdir
C:\Users\Administrator\Desktop
ftp> get Myself
200 PORT command successful. Consider using PASV.
150 Opening ASCII mode data connection for Myself (986 bytes).
226 Transfer complete.
ftp: 收到 1004 字节,用时 0.00秒 1004.00千字节/秒。
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r-- 1 500 500 986 Dec 03 10:08 Myself
-rw-r--r-- 1 500 500 233 Dec 03 10:07 Myself.pub
226 Directory send OK.
ftp: 收到 132 字节,用时 0.00秒 132.00千字节/秒。
ftp> !dir
驱动器 C 中的卷没有标签。
卷的序列号是 941F-307E

C:\Users\Administrator\Desktop 的目录

2013/12/03 18:27 <DIR> .
2013/12/03 18:27 <DIR> ..
2013/11/17 13:23 932 Evernote.lnk
2013/11/24 15:43 1,023 FlashFXP.lnk
2013/11/21 08:53 2,176 Git Shell.lnk
2013/11/21 08:53 308 GitHub.appref-ms
2013/12/03 18:27 1,004 Myself
2013/10/26 21:26 1,627 SecureCRT.lnk
6 个文件 7,070 字节
2 个目录 50,591,227,904 可用字节
ftp>

5.断开连接

  bye 就是这样。

1
2
3
4
5
6
7
8
ftp> status
连接到 169.254.234.241。
类型: ascii;详细: 开 ;铃声: 关 ;提示: 开 ;通配: 开
调试: 关 ;哈希标记打印: 关 。
ftp> bye
221 Goodbye.

C:\Users\Administrator>

6.总结

  这里就是拿一个例子来说明了一下简单的上传和下载命令的使用。使用 help 和 help [Command] 来查看对应命令的解释。最后给出常用命令的说明和格式。

命令 说明 格式 参数说明
bye 结束与远程计算机的 FTP 会话并退出 ftp bye
cd 更改远程计算机上的工作目录 cd RemoteDirectory ***RemoteDirectory***指定要更改的远程计算机上的目录。
dir 显示远程计算机上的目录文件和子目录列表 dir [RemoteDirectory] [LocalFile] ***RemoteDirectory***指定要查看其列表的目录。如果没有指定目录,将使用远程计算机中的当前工作目录。 ***LocalFile***指定要存储列表的本地文件。如果没有指定本地文件,则屏幕上将显示结果。
get 使用当前文件传输类型将远程文件复制到本地计算机。如果没有指定 LocalFile,文件就会赋以 RemoteFile 名。get 命令与 recv 相同。 get RemoteFile [LocalFile] ***RemoteFile***指定要复制的远程文件。 ***LocalFile***指定要在本地计算机上使用的文件名。
lcd 更改本地计算机上的工作目录。默认情况下,工作目录是启动 ftp 的目录 lcd [Directory] ***Directory***指定要更改的本地计算机上的目录。如果没有指定 Directory,将显示本地计算机中的当前工作目录。
ls 显示远程目录上的文件和子目录的简短列表 ls [RemoteDirectory] [LocalFile] ***RemoteDirectory***指定要查看其列表的目录。如果没有指定目录,将使用远程计算机中的当前工作目录。 ***LocalFile***指定要存储列表的本地文件。如果没有指定本地文件,将在屏幕上显示结果。
open 与指定的 FTP 服务器连接。可以使用 IP 地址或计算机名(两种情况下都必须使用 DNS 服务器或主机文件)指定 Computer。 open Computer [Port] ***Computer***必需。指定试图要连接的远程计算机。 ***Port***指定用于联系 FTP 服务器的 TCP 端口号。默认情况下,使用 TCP 端口号 21。
put(send) 使用当前文件传输类型将本地文件复制到远程计算机上。put 命令与 send 命令相同。如果没有指定 RemoteFile,文件就会赋以 LocalFile 名。 put LocalFile [RemoteFile] ***LocalFile***指定要复制的本地文件。 ***RemoteFile***指定要在远程计算机上使用的名称。