python 在ftp创建文件
暑假做的唯一一个有意义的项目吧,其实原理很简单。主要是其中学了不少Ubuntu的东西。今天正好没事,整理一下,以便后面查阅。
首先推荐一个好用的FTP管理程序--IIS7服务器管理工具:
“IIS7服务器管理工具是一款windows全系、Linux系统下链接并操控VPS、VNC、FTP等远程服务器、云服务器。
界面简单明了,操作易上手,功能强大,支持批量导入服务器,并批量打开,多窗口化管理,除此之外,加载本地硬盘、硬盘映射、加载服务器的声音,远程声卡读取等,完全实现各类场景使用,对于FTP链接界面,朋友FTP定时上传,定时下载(也可以说定时上传下载 定时备份),对于经常使用FTP的小伙伴来说,非常适用。
工具支持自动更新,压缩包只有7.62M,方便简洁,一步到位。“
使用说明:
一、 程序说明。
程序功能:这个程序主要由三个功能。1.浏览ftp服务器目录。2.随机下载一个文件。3.随机下载多个文件。
1. 浏览ftp服务器目录。
这个功能主要是在登入进ftp服务器后,生成一个随机数,根据随机数,进行判断往哪个目录下索引。如果是根目录,只会向下索引。如果是底层目录,只会向上索引。
2. 随机下载一个文件。
这个功能主要是在登入进ftp服务器后,生成一个随机数,根据随机数,随机下载一个文件。需要注意的是,生成随机数之前,要进行判断。如果没有要下载的文件,就要切换目录,进行下载。
3. 随机多个文件下载
这个功能主要是在登入ftp服务器后,随机下载多个文件。实现原理为,首先进入一个目录下,判断是否有文件下载,如果有文件下载,则下载多个文件,如果没有,则改变目录。完成后改变目录。
所需参数:“ip,port,username,passwd,usermodel”。传入参数由一个字符串组成。用逗号进行分割。
所需环境:需要搭建好ftp服务器。以及有python环境的系统上运行。
注意事项:
1. 下载路径默认为”/home/”。如果程序出错提示为“不能写入”,需要对文件权限进行提升。
2. 在实现用户模式时,程序已经默认多次执行。即每次运行程序时,就会随机多次(至少一次,最多5次)执行,用来模拟用户行为。
3. ftp服务器搭建详见ftp服务器搭建教程。
1 #!/usr/bin/env Python3
2 #-*- encoding:utf-8 -*-
3 from ftplib importFTP4 from random importrandint5 importtime6 importsys7
8
9
10
11 defftpconnect(ip, port, username, passwd):12 ftp =FTP()13 #ftp.set_debuglevel(2) # 打开调试级别2,显示详细信息
14 ftp.connect(ip, port) #连接的ftp服务器ip和port
15 ftp.login(username, passwd) #连接的用户名和密码
16 print(ftp.getwelcome()) #打印出欢迎信息。
17 returnftp18
19 defshowdownloadfile(ftp):20 #print("当前目录下的文件:文件夹名字:"+ftp.pwd())
21 mu_dir =gettable(ftp)22 #print("当前文件夹: "+ftp.pwd()+" 可供下载的文件:")
23 behind_name =[]24 for name inmu_dir:25 if mu_dir[name] == "文件":26 behind_name.append(name)27 #print(name)
28 returnbehind_name29
30 defshowfolderfile(ftp):31 #print("当前目录下的文件:文件夹名字:"+ftp.pwd())
32 mu_dir =gettable(ftp)33 #print("当前文件夹: "+ftp.pwd()+" 可供索引的文件夹:")
34 folder_name =[]35 for name inmu_dir:36 if mu_dir[name] == "文件夹":37 folder_name.append(name)38 #print(name)
39 returnfolder_name40
41 defrandomdownload(ftp, localpath, str):42 #当前目录下可供下载的文件名字
43 behind_name =showdownloadfile(ftp)44 #print("当前文件夹: "+ftp.pwd()+" 可供下载的文件:")
45 #print(behind_name)
46 #随机数
47 while len(behind_name) == 0: #说明没有可以下载的文件
48 #切换文件夹
49 changetable(ftp,str)50 behind_name =showdownloadfile(ftp)51 file_random = randint(0, len(behind_name)-1)52 filename =behind_name[file_random]53 print("当前目录为:"+ftp.pwd())54 print("下载文件为"+filename)55 #设置下载数据
56 bufsize = 1024 #设置缓冲区大小
57 new_path = localpath+filename #设置下载路径
58
59 fp = open(new_path, 'wb')60 ftp.retrbinary('RETR' + filename, fp.write, bufsize) #下载FTP文件。FTP命令 RETR filename
61 fp.close()62 print(filename+'下载成功')63
64
65 def downloadfiles(ftp, localpath, str): #根目录不能继续向下,没有目录不能索引(这个可以自动实现)。
66 #在当前目录下随机下载几个文件
67 behind_name =showdownloadfile(ftp)68 #folder_name = showfolderfile(ftp)
69 while len(behind_name) == 0: #说明没有可以下载的文件
70 #切换文件夹
71 changetable(ftp, str)72 behind_name =showdownloadfile(ftp)73
74 randomb = randint(0, len(behind_name)-1)75 while randomb: #在这个文件夹下随机下载几个
76 randomdownload(ftp, localpath, str)77 randomb -= 1
78 #切换目录下载(可能向下或者向上)
79 #viewtable(ftp)
80
81
82
83
84 def gettable(ftp): #获取目录结构
85 dir_del =[]86
87 table_dir ={}88 ftp.dir('.', dir_del.append) #根据文件目录,进行拆分。
89 for name indir_del:90 strname =str(name)91 temp = strname.split(' ')92 attrname =[]93 for j inrange(0,len(temp)):94 if temp[j] != '':95 attrname.append(temp[j])96 m = ' '.join(attrname[8:])97 if strname.startswith('d'):98 #print('文件夹:', m)
99 table_dir[m] = '文件夹'
100 else:101 #print('文件:', m)
102 table_dir[m] = '文件'
103 return table_dir #字典,key值是文件名,value是类型
104
105 defviewtable(ftp,str):106 #gettable(ftp) # 获取当前目录
107 changtimes = randint(1, 4) #随机切换几次目录
108 whilechangtimes:109 changtimes -= 1
110 folder_name =showfolderfile(ftp)111 print("当前目录下为:"+ftp.pwd())112 print("目录结构:")113 print(gettable(ftp))114 if len(folder_name) > 0: #有可供索引的文件夹
115 if ftp.pwd() == str: #为根目录,只能向下索引
116 print("向下索引后目录为:")117 randomf = randint(0, len(folder_name)-1)118 path = ftp.pwd()+folder_name[randomf]119 ftp.cwd(path)120 print("当前目录下为:"+ftp.pwd())121 print("目录结构:")122 print(gettable(ftp))123
124 else: #向上向下索引都可以
125 downorup = randint(0, 1)126 if downorup: #向下索引
127 print("向下索引后目录为:")128 randomf = randint(0, len(folder_name)-1)129 path = ftp.pwd()+folder_name[randomf]130 ftp.cwd(path)131 print("当前目录下为:"+ftp.pwd())132 print("目录结构:")133 print(gettable(ftp))134
135 else:136 print("向上索引后,目录为:")137 path = '../'
138 ftp.cwd(path)139 print("当前目录下为:"+ftp.pwd())140 print("目录结构:")141 print(gettable(ftp))142 else: #没有可供索引的文件夹,可以向上索引。
143 if ftp.pwd() !=str:144 print("向上索引后,目录为:")145 path = '../'
146 ftp.cwd(path)147 print("当前目录下为:"+ftp.pwd())148 print("目录结构:")149 print(gettable(ftp))150
151 defchangetable(ftp,str):152 folder_name =showfolderfile(ftp)153 if len(folder_name) > 0: #有可供索引的文件夹
154 if ftp.pwd() == str: #为根目录,只能向下索引
155 randomf = randint(0, len(folder_name)-1)156 path = ftp.pwd()+folder_name[randomf]157 ftp.cwd(path)158
159 else: #向上向下索引都可以
160 downorup = randint(0, 1)161 if downorup: #向下索引
162 randomf = randint(0, len(folder_name)-1)163 path = ftp.pwd()+folder_name[randomf]164 ftp.cwd(path)165
166 else:167 path = '../'
168 ftp.cwd(path)169 else: #没有可供索引的文件夹,可以向上索引。
170 if ftp.pwd() !=str:171 path = '../'
172 ftp.cwd(path)173 defftpmain(ip, port, username, passwd, localpath, userModel):174 #1.连接到ftp服务器
175 ftp =ftpconnect(ip, port, username, passwd)176 #2.开始交互
177 str =ftp.pwd()178 #print(str)
179 #usermodel 也可以是一个列表序列,让一个用户,执行多个操作。
180 cmdtimes = randint(1, 5) #这随机多次执行用户模式。
181 #downloadtimes = 3 # 多个文件多次下载
182 whilecmdtimes:183 cmdtimes -= 1
184 if userModel == 1: #浏览模式
185 viewtable(ftp, str)186 changetable(ftp, str)187 continue
188 if userModel == 2: #下载模式
189 randomdownload(ftp, localpath, str)190 changetable(ftp, str)191 continue
192 if userModel == 3: #同时下载多个文件模式
193 #while downloadtimes:
194 downloadfiles(ftp, localpath, str)195 changetable(ftp, str)196 #downloadtimes -= 1
197 continue
198 else: #错误处理机制
199 print('无法识别传递的模式编号:')200 break
201
202 ftp.quit()203
204
205 if __name__ == "__main__":206 agrvlist = sys.argv[1].split(',')207 ip =agrvlist[0]208 port = int(agrvlist[1])209 username = agrvlist[2]210 passwd = agrvlist[3]211 usermodel = int(agrvlist[4])212 ftpmain(ip, port, username, passwd, "/home/username/", usermodel)
View Code
从程序中我们可以看出,其实还是很简单的。主要是引入ftplib库。用pip就可以。
下面简单说一下,我在编程中主要遇到的问题:
1.区分ftp服务器里面的文件夹和文件。
这里是解决的方法:
1 def gettable(ftp): #获取目录结构
2 dir_del =[]3
4 table_dir ={}5 ftp.dir('.', dir_del.append) #根据文件目录,进行拆分。
6 for name indir_del:7 strname =str(name)8 temp = strname.split(' ')9 attrname =[]10 for j inrange(0,len(temp)):11 if temp[j] != '':12 attrname.append(temp[j])13 m = ' '.join(attrname[8:])14 if strname.startswith('d'):15 #print('文件夹:', m)
16 table_dir[m] = '文件夹'
17 else:18 #print('文件:', m)
19 table_dir[m] = '文件'
20 return table_dir #字典,key值是文件名,value是类型
View Code
主要是先获取服务器文件夹里面的详细信息,通过分析,利用python的数据结构来区分。
下面是我的分析过程:
这是ftp服务器主目录下,通过ftp.dir(),然后输出结果为:
['drwxrwxrwx 2 0 0 4096 Jul 04 21:17 hello', '-rw------- 1 1001 131 3 Jul 05 10:20 test', '-rwxrwxrwx 1 1000 1000 2840284 Apr 20 2016 test.ogg']
通过查阅发现:hello是文件夹,test和test.ogg是文件。
然后进一步查分,最后通过'd'来区分。
strname.startswith('d')
2.获取外部输入
这个程序不是直接编译通过的,而是要传递外部参数。利用sys库进行操作。通过控制台运行函数。
1 if __name__ == "__main__":2 agrvlist = sys.argv[1].split(',')3 ip =agrvlist[0]4 port = int(agrvlist[1])5 username = agrvlist[2]6 passwd = agrvlist[3]7 usermodel = int(agrvlist[4])
View Code
由于 外部参数都是以字符串形式传入,所以要进行格式转换操作。
3.限制下载速度。
这个功能在程序中没有实现。后来通过阅读关于网络的书籍,关于tcp的过程,其实是可以通过设置缓冲区的大小来模拟延迟的。当然这个下载速度服务器是由主导权的。
这个项目主要学到的东西在ftp服务器搭建中,放到下个随笔中。