模拟百度云盘版的ftp

思路:
一、分两个大的文件夹,一个是客户端,一个服务端的

二、实现的功能

    1.    登陆--对用户名的合法性进行检测(实验账户:alex,123)
        
        注册--设置账户,其中网盘列表设置为空,刚注册的用户给到50下载豆

        规则:
            
            用户上传文件是上传到服务端的共享文件库里,同时会添加到自己的网盘里,
            上传一个文件就可以奖励50下载豆,并自己上传的文件以后下载不用下载豆

            用户去找资源,其实就是把服务端的共享文件库陈列给客户看,客户如果把
            服务端的资源文件添加到自己的网盘,必须消耗20下载豆

            用户下载不用消耗下载豆,但是只能从自己的网盘里下载

    2.进入到FTP客户可以选择:

        上传--

            遍历自己本地文件库,选择上传,上传过程中显示进度条(支持断点续传)
            
        下载--

            遍历自己的网盘,选择下载,下载过程中显示进度条(支持断点下载)

        找资源--

            遍历服务端的共享文件库,选择添加到自己的网盘

        查看我的网盘--

            遍历自己的网盘展示

 

流程图

 

代码实现

目录:

client端:

  client_main.py

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
import os
import sys
 
pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pat)
 
from config import Config
 
import socket
import time
import json
 
def main():
    #连接服务器
    ip_port = ('127.0.0.1',8009)
    sk = socket.socket()
    sk.connect(ip_port)
 
    #接收欢迎信息
    bt = sk.recv(1024)
    print(str(bt,encoding='utf-8'))
 
 
    flag1 = 1
    while flag1:
        # 让客户选择操作
        print('\t1\t登陆\n\t2\t注册')
        choose = input('请选择序号选择你的操作:')
        if choose == '2':
            sk.sendall(bytes(choose,encoding='utf-8'))
            print('注册页面!')
 
            while True:
                reg_usr = input('请输入注册用户名:')
                sk.sendall(bytes(reg_usr,encoding='utf-8'))
 
                ret = str(sk.recv(1024),encoding='utf-8')
                if ret == '合法':
                    reg_pwd = input('请输入注册密码:')
                    sk.sendall(bytes(reg_pwd,encoding='utf-8'))
                    bt = sk.recv(1024)
                    print(str(bt,encoding='utf-8'))
                    break
                else:
                    print(ret)
 
        elif choose == '1':
            sk.sendall(bytes(choose, encoding='utf-8'))
            print('登陆页面!')
 
            flag2 = 1
            while flag2:
                landed_usr = input('请输入用户名:')
                sk.sendall(bytes(landed_usr,encoding='utf-8'))
 
                ret = str(sk.recv(1024), encoding='utf-8')
                if ret == '存在':
                    while True:
                        landed_pwd = input('请输入密码:')
                        sk.sendall(bytes(landed_pwd,encoding='utf-8'))
                        bt = sk.recv(1024)
                        if str(bt,encoding='utf-8') == 'yes':
                            print('登陆成功!')
                            flag1 = 0
                            flag2 = 0
                            enter_flag = 1
                            break
                        else:
                            print(str(bt, encoding='utf-8'))
                else:
                    print('用户名不存在!请重新输入!')
 
        else:
            print('输入有误!请重新输入!')
 
    #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
    while enter_flag:
        print('\n\t1\t上传\n'
              '\t2\t下载\n'
              '\t3\t找资源\n'
              '\t4\t查看我的网盘\n')
        choose = input('请选择你接下来的操作(输入q退出):')
        #把客户的选择发过去
        sk.sendall(bytes(choose, encoding='utf-8'))
        if choose == '1':
            #遍历本地文件,并让客户选择
            for k,file_name in enumerate(Config.local_file_list,1):
                print(k,file_name)
            m = input('请选择你要上传的文件:')
            file_name = Config.local_file_list[int(m)-1]
            print(file_name)
 
            #把文件名发过去
            sk.sendall(bytes(file_name,encoding='utf-8'))
            print('文件名已发过去!')
            #接收检测的文件大小
            file_size = str(sk.recv(1024),encoding='utf-8')
            print('文件大小已收到!',file_size)
 
            file_name_path = os.path.join(Config.PATH,file_name)
            all_size = os.stat(file_name_path).st_size
            print('总大小:',all_size)
            if all_size != int(file_size):
                with open(file_name_path,'rb') as f:
                    num = int(file_size)
                    f.seek(num)
 
                    for line in f:
                        sk.sendall(line)
                        file_size = str(sk.recv(1024),encoding='utf-8')
                        sys.stdout.write('\r'# 每一次清空原行
                        sys.stdout.write('%s%% |%s' % (int( int(file_size)/ all_size * 100),
                                                       int(int(file_size) / all_size / 2 * 100) * '*'))
                        sys.stdout.flush()  # 强制刷新缓冲区
                        time.sleep(0.3)
                    sk.sendall(bytes('1',encoding='utf-8'))
                    print('\n上传完毕!')
 
            else:
                print('你要上传的文件已存在!')
 
 
        elif choose == '2':
            s = str(sk.recv(1024), encoding='utf-8')
            my_wangpan = json.loads(s)
            print('我的网盘:')
            for n, file_na in enumerate(my_wangpan, 1):
                print(n, file_na)
            load_choose = input('请输入序号选择你要下载的文件:')
 
            sk.sendall(bytes(load_choose,encoding='utf-8'))
            all_size = str(sk.recv(1024),encoding='utf-8')
            print(type(all_size),all_size)
            load_file_name = my_wangpan[int(load_choose) - 1]
 
            pth = os.path.join(Config.PATH, load_file_name)
            if load_file_name in Config.local_file_list:
                file_size = os.stat(pth).st_size
 
                if str(file_size) == all_size:
                    sk.sendall(bytes('下载过',encoding='utf-8'))
                    sk.recv(1024)
                    print('你本地文件里已有要下载的文件!')
 
                else:
                    print('继续下载...')
                    sk.sendall(bytes('下载了一点点',encoding='utf-8'))
                    sk.recv(1024)
                    sk.sendall(bytes(str(file_size),encoding='utf-8'))
                    with open(pth,'ab') as f:
                        while True:
                            bt = sk.recv(1024)
                            if int(file_size / int(all_size)) == 1:
                                break
                            else:
                                f.write(bt)
                                file_size += len(bt)
                                sys.stdout.write('\r'# 每一次清空原行
                                sys.stdout.write('%s%% |%s' % (int(file_size / int(all_size) * 100),
                                                               int(file_size / int(all_size) / 2 * 100) * '*'))
                                sys.stdout.flush()  # 强制刷新缓冲区
                                time.sleep(0.3)
                    print('\n下载完成!')
 
            else:
                print('开始下载...')
                sk.sendall(bytes('没下载',encoding='utf-8'))
                sk.recv(1024)
                file_size = 0
                sk.sendall(bytes('0',encoding='utf-8'))
                with open(pth, 'wb') as f:
                    while True:
                        bt = sk.recv(1024)
                        if int(file_size / int(all_size)) == 1:
                            break
                        else:
                            f.write(bt)
                            file_size += len(bt)
                            sys.stdout.write('\r'# 每一次清空原行
                            sys.stdout.write('%s%% |%s' % (int(file_size / int(all_size) * 100),
                                                           int(file_size / int(all_size) / 2 * 100) * '*'))
                            sys.stdout.flush()  # 强制刷新缓冲区
                            time.sleep(0.3)
                print('下载完成!')
 
        elif choose == '3':
            print('进入!')
            s = str(sk.recv(1024),encoding='utf-8')
            print('收到json字符')
            li = json.loads(s)
 
            print('资源如下:')
            for m,file_name in enumerate(li,1):
                print(m,file_name)
            choose = input('请选择序号决定你想要添加到网盘的文件(添加一个文件减少20下载豆):')
            sk.sendall(bytes(choose,encoding='utf-8'))
            print(str(sk.recv(1024),encoding='utf-8'))
 
 
        elif choose == '4':
            s = str(sk.recv(1024),encoding='utf-8')
            my_wangpan = json.loads(s)
            print('我的网盘:')
            for n,file_na in enumerate(my_wangpan,1):
                print(n,file_na)
 
        elif choose.lower() == 'q':
            exit()
 
        else:
            print('你输入有误!请重新输入!')
 
if __name__ == '__main__':
    main()

   config.py

1
2
3
4
5
6
7
import os
import sys
 
pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
PATH = os.path.join(pat,'db')
local_file_list = os.listdir(PATH)

 

server端

  server_main.py

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import os
import sys
pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pat)
 
from lib import account
from config import Config
 
import socketserver
import json
import time
import pickle
 
class MyServer(socketserver.BaseRequestHandler):
 
    def handle(self):
        # print self.request,self.client_address,self.server
        conn = self.request
        conn.sendall(bytes('欢迎来到百度云盘!',encoding='utf-8'))
 
        flag1 = 1
        while flag1:
            choose = str(conn.recv(1024), encoding='utf-8')
            if choose == '2':
 
                while True:
                    reg_usr = str(conn.recv(1024),encoding='utf-8')
                    ret = account.usr_ver(reg_usr)
                    conn.sendall(bytes(ret,encoding='utf-8'))
 
                    if ret == '合法':
                        reg_pwd = str(conn.recv(1024),encoding='utf-8')
                        hash_pwd = account.encrypt(reg_pwd)
                        ob = account.Account()
                        ob.registered(reg_usr,hash_pwd)
                        account.info_add(ob)
                        conn.sendall(bytes('注册成功!',encoding='utf-8'))
                        break
 
            elif choose == '1':
 
                flag2 = 1
                while flag2:
                    landed_usr = str(conn.recv(1024),encoding='utf-8')
                    ret = account.land_usr_ver(landed_usr)
                    conn.sendall(bytes(ret,encoding='utf-8'))
 
                    if ret == '存在':
                        while True:
                            landed_pwd = str(conn.recv(1024),encoding='utf-8')
                            obj = account.landed_ver(landed_usr,landed_pwd)
                            if isinstance(obj,account.Account):
                                conn.sendall(bytes('yes', encoding='utf-8'))
                                flag1 = 0
                                flag2 = 0
                                break
                            else:
                                conn.sendall(bytes(obj, encoding='utf-8'))
        #########################################################################################
 
        while True:
            #接收客户的操作选择
            choose = str(conn.recv(1024),encoding='utf-8')
            if choose == '1':
                #接收客户发来需要上传的文件名
                file_name = str(conn.recv(1024),encoding='utf-8')
                pat = os.path.join(Config.PATH,file_name)
                #判断上传的文件是否存在
                if file_name in Config.shared_file_list:
                    file_size = os.stat(pat).st_size
                    #对存在的文件,检测大小,把值传过去
                    conn.sendall(bytes(str(file_size),encoding='utf-8'))
                    with open(pat,'ab') as f:
                        flag = 1
                        while flag:
                            bt = conn.recv(1024)
                            if len(bt) == 1 and bt == bytes('1',encoding='utf-8'):
                                flag = 0
                            else:
                                f.write(bt)
                                file_size += len(bt)
                                conn.sendall(bytes(str(file_size), encoding='utf-8'))
                        obj.netdisc.append(file_name)
                        obj.download_beans += 50
 
                else:
                    conn.sendall(bytes('0',encoding='utf-8'))
                    file_size = 0
                    with open(pat,'wb') as f:
                        flag = 1
                        while flag:
                            bt = conn.recv(1024)
                            if len(bt) == 1 and bt == bytes('1', encoding='utf-8'):
                                flag = 0
                            else:
                                f.write(bt)
                                file_size += len(bt)
                                conn.sendall(bytes(str(file_size), encoding='utf-8'))
                        obj.netdisc.append(file_name)
                        obj.download_beans += 50
 
 
 
            elif choose == '2':
                s = json.dumps(obj.netdisc)
                conn.sendall(bytes(s, encoding='utf-8'))
 
                load_choose = str(conn.recv(1024),encoding='utf-8')
                index_num = int(load_choose) - 1
                download_file_name = obj.netdisc[index_num]
                pat = os.path.join(Config.PATH,download_file_name)
                all_size = os.stat(pat).st_size
                print(type(all_size),all_size)
                conn.sendall(bytes(str(all_size),encoding='utf-8'))
 
                if str(conn.recv(1024),encoding='utf-8') != '下载过':
                    conn.sendall(bytes('知道',encoding='utf-8'))
                    seek_num = int(str(conn.recv(1024),encoding='utf-8'))
                    with open(pat,'rb') as f:
                        f.seek(seek_num)
                        for line in f:
                            conn.sendall(line)
                        time.sleep(3)
                        conn.sendall(bytes('0',encoding='utf-8'))
 
                else:
                    conn.sendall(bytes('知道', encoding='utf-8'))
 
 
            elif choose == '3':
                print('进入!')
                s = json.dumps(Config.shared_file_list)
                conn.sendall(bytes(s,encoding='utf-8'))
                print('已发出json格式信息')
 
                #收到客户选择信息
                choose = str(conn.recv(1024),encoding='utf-8')
                index_num = int(choose) - 1
                index_file_name = Config.shared_file_list[index_num]
                print(index_file_name)
                if obj.download_beans >= 20:
                    obj.netdisc.append(index_file_name)
                    obj.download_beans -= 20
                    conn.sendall(bytes('添加成功',encoding='utf-8'))
                else:
                    conn.sendall(bytes('下载豆不足!添加失败!',encoding='utf-8'))
 
            elif choose.lower() == 'q':
                with open(Config.ACCOUNT_INFO_PATH,'rb') as f:
                    li = pickle.loads(f.read())
                    lis = []
                    for i in li:
                        if i.username == obj.username:
                            lis.append(obj)
                        else:
                            lis.append(i)
                with open(Config.ACCOUNT_INFO_PATH,'wb') as f:
                    f.write(pickle.dumps(lis))
 
 
            elif choose == '4':
                s = json.dumps(obj.netdisc)
                conn.sendall(bytes(s,encoding='utf-8'))
 
 
 
if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
    server.serve_forever()

   config.py

1
2
3
4
5
6
7
8
9
import os
import sys
pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pat)
 
 
ACCOUNT_INFO_PATH = os.path.join(pat,'db','用户信息.log')
PATH = os.path.join(pat,'db','共享文件')
shared_file_list = os.listdir(PATH)

   account.py

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
91
92
93
94
95
import os
import sys
pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pat)
 
from config import Config
 
import pickle
import hashlib
 
class Account:
 
    def __init__(self):
        self.username = None
        self.password = None
        self.download_beans = 0
        self.netdisc = []
 
    def registered(self,usr,pwd):
        self.username = usr
        self.password = pwd
        self.download_beans = 50
 
 
def usr_ver(usr):
    '''
    注册时验证用户名存不存在
    :param usr: 需要验证用户名
    :return: 存在--返回用户名已存在,不存在--返回合法
    '''
    if os.path.exists(Config.ACCOUNT_INFO_PATH):
        with open(Config.ACCOUNT_INFO_PATH,'rb') as f:
            li = pickle.load(f)
            for i in li:
                if i.username == usr:
                    return '用户名已存在!请重新输入!'
            return '合法'
    else:
        return '合法'
 
def encrypt(pwd):
    '''
    給密码加密的
    :param pwd: 需要加密的密码
    :return: 返回加密后的哈西值
    '''
    m = hashlib.md5(bytes('明天更美好',encoding='utf-8'))
    m.update(bytes(pwd,encoding='utf-8'))
    return m.digest()
 
def info_add(obj):
    '''
    把注册好信息写入文件
    :param obj: 注册的账户对象
    :return:
    '''
    if os.path.exists(Config.ACCOUNT_INFO_PATH):
        with open(Config.ACCOUNT_INFO_PATH,'rb') as f:
            li = pickle.load(f)
            li.append(obj)
    else:
        li = []
        li.append(obj)
    with open(Config.ACCOUNT_INFO_PATH, 'wb') as f:
        pickle.dump(li,f)
 
def land_usr_ver(usr):
    '''
    登录时验证用户名存不存在
    :param usr: 需要验证用户名
    :return: 存在--返回存在,不存在--返回你输入的用户名不存在
    '''
    if os.path.exists(Config.ACCOUNT_INFO_PATH):
        with open(Config.ACCOUNT_INFO_PATH,'rb') as f:
            li = pickle.load(f)
            for i in li:
                if i.username == usr:
                    return '存在'
            return '输入的用户名不存在!请重新输入!'
    else:
        return '输入的用户名不存在!请重新输入!'
 
def landed_ver(usr,pwd2):
    '''
    用于用户名和密码验证
    :param usr: 验证用户名
    :param pwd: 验证密码
    :return:
    '''
    pwd = encrypt(pwd2)
    li = pickle.load(open(Config.ACCOUNT_INFO_PATH,'rb'))
    for i in li:
        if i.username == usr and i.password == pwd:
            return i
    return '密码错误!请重新输入!'

 

绝版FTP:猛戳这里

 



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   财经知识狂魔  阅读(2074)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示