模拟百度云盘版的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:猛戳这里

时间: 2024-10-25 22:35:05

模拟百度云盘版的ftp的相关文章

Python--select版的FTP

1.要求 用select模块实现FTP上传文件和下载文件的功能 2.目录 3.实现,主要修改的还是server的代码 client端 1 import socket 2 import os 3 from lib import * 4 5 def download(): 6 msg = 'download ' 7 #显示要下载的目录中的文件 8 filename=input('输入你要下载的文件名(保存到当前路径)') 9 msg +=filename 10 return msg 11 12 de

最新破解版Coade CADWorx 2012 1CD(全模块)

Synergee gas V4.50 Schlumberger PIPESIM v2010.1 (v2009.1) Coade caesar V5.30.3 (V5.30.1,v5.2,v5.1) Coade PVelite v2012(v2010) Flaresim v3.04 SIMSCI pipephase v9.5(v9.4) SIMSCI visualflow v5.4(v5.4) SIMSCI PROII v9.1 SIMSCI inplant v4.2 Pvtsim V20.0(v

KBC.Petro-SIM.Suite.V6.1.build.1416炼油工艺流程模拟

CAESAR II 2016 v8.00.00.5600 build 150930管道设计应力分析 DNV GL AS Phast v7.11.33.0 风险分析KBC.Petro-SIM.Suite.V6.1.build.1416炼油工艺流程模拟Invensys SimSci-Esscor PRO/II v9.4 1CD化工流程模拟完美版PVELITE.2016.V18.00.00.0000 最著名的压力容器设计软件CAESAR II 2016 v8.00.00.5600 build 1509

Spt Olga v7.1(v6.3, V6.2) 全动态多相流模拟计算程序

Code V.v10.4.SP1 LightTools.v7.3 Stoner Pipeline Simulator v9.9.0(v9.7.2, v9.6, v9.5) (SPS)建立了鄯乌管道离线电子管道系统,借助Visual Basic(VB)程序开发语言,开发了具有与现场一致的SCADA系统操作界面,应用SPS软件与VB语言接口,建立了前台操作界面与后台电子管道之间的实时连接独家所有,功能完整,可远程测试.Synergee gas V4.52 储气田和集气井仿真建模和分析 Schlumb

用PHP实现一个高效安全的ftp服务器(一)

摘要: 本文主要阐述使用PHP的swoole扩展实现ftp服务器,同时扩展ftp服务器个性化功能和安全性.真正实现一个自己完全掌控的ftp服务器,可以个性化定制的ftp服务器. 正文: FTP服务器想必大家都不陌生,使用起来,现成的软件也很多.不过免费的软件功能有时候并不符合自己需求,又无法二次开发,付费软件价格又比较高昂.PHP的swoole扩展,是PHP语言的高性能网络通信框架,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,数据库连接池,AsyncTask

FTP协议总结

说明:本文仅供学习交流,转载请标明出处,欢迎转载! FTP协议(文件传输协议)建立在TCP协议的基础之上,用来从一个主机把文件复制到另外一个主机.在FTP客户机与服务器之间,采用来了两条TCP连接,这两条连接分别是控制连接和数据连接.在控制连接过程中,FTP服务器使用的端口号为21,在数据连接过程中,FTP服务使用的端口号为20,而客户机在整个过程中使用的端口号都是临时端口号,这两个临时端口号可以相同,也可以不同,当然在绝大多数情况下,这两个临时端口号都是不同的.在整个从连接的发起到数据传输的整

Android实现模拟表单上传

很久以前,写过一篇关于下载的文章:基于HTTP协议的下载功能实现,今天对于Android上的文件上传,也简单的提两笔.在Android上,一般使用Http 模拟表单或者FTP来进行文件上传,使用FTP协议,可以直接使用Appache的FTPClient,使用方法很简单,不再赘述.这里主要说明一下Http模拟表单上传的实现. 模拟表单上传,其实也很简单,主要需要在Http post 的数据体中构建表单信息(multipart/form),表单数据格式的规范,可以参考REC标准.下面是一个格式示例:

事故后果模拟、安全风险计算软件 Dnv.Phast.V7.01

Dnv.Phast.V7.01事故后果模拟.安全风险计算软件 DNV Phast & Safeti v6.53.1DNV Leak v3.2石油化工装置风险分析DNV Phast & Safeti v6.51 1CD(事故后果模拟.安全风险计算软件,五模块全部功能版)DNV Leak v3.2石油化工装置风险分析DNV Phast 6.53.1 1CD软件为五模块全部功能版SAFETI Micro 6.53SAFETI 6.53PHAST Micro 6.53PHAST FX 6.53PH

Ftp、Ftps与Sftp之间的区别

Ftp FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为"文传协议".用于Internet上的控制文件的双向传输.同时,它也是一个应用程序(Application).基于不同的操作系统有不同的FTP应用程序,而所有这些应用程序都遵守同一种协议以传输文件.在FTP的使用当中,用户经常遇到两个概念:"下载"(Download)和"上传"(Upload)."下载"文件就是从远程主机拷贝文