zoukankan      html  css  js  c++  java
  • 模拟百度云盘版的ftp

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

    二、实现的功能

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

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

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

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

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

            上传--

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

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

            找资源--

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

            查看我的网盘--

                遍历自己的网盘展示

    流程图

    代码实现

    目录:

    client端:

      client_main.py

    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('	1	登陆
    	2	注册')
            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('
    	1	上传
    '
                  '	2	下载
    '
                  '	3	找资源
    '
                  '	4	查看我的网盘
    ')
            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('
    ')  # 每一次清空原行
                            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('
    上传完毕!')
    
                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('
    ')  # 每一次清空原行
                                    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('
    下载完成!')
    
                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('
    ')  # 每一次清空原行
                                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

    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

    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

    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

    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:猛戳这里

  • 相关阅读:
    点击cell后 cell的背景不变,cell上的字体颜色发生改变的功能实现
    各种属性设置
    多列表 ,菜单
    正则表达式
    多个storyboard之间的跳转问题
    关于uicollectionview的个人学习
    uiscrollview的自动布局
    手动自动布局
    关于简单的跳转问题
    深入理解@class和#import的区别
  • 原文地址:https://www.cnblogs.com/xinsiwei18/p/5913999.html
Copyright © 2011-2022 走看看