模拟百度云盘版的ftp

Posted 财经知识狂魔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟百度云盘版的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(\'\\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

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

 

以上是关于模拟百度云盘版的ftp的主要内容,如果未能解决你的问题,请参考以下文章

第三方阿里云盘安卓 TV 版,可直接播放视频文件

PyQt5学习记录---监听鼠标拖拽事件实现Mac上百度云盘拖拽效果

PyQt5学习记录---监听鼠标拖拽事件实现Mac上百度云盘拖拽效果

跟着百度学PHP[17]-PHP扩展CURL的用法详解

Linux项目——ftp云盘

c#的百度云盘API