【小程序】支持多用户在线的FTP程序

功能:
1.用户加密认证;

2.允许同时多用户登陆;

3.每个用户有自己的家目录,并且只能访问在自己的家目录;

4.对用户进行磁盘配额,每个用户的可用空间不同;

5.允许用户在ftp server上随意切换目录;

6.允许用户查看当前目录上下文;

7.允许用户上传和下载文件,保证文件的一致性

8.文件传输过程中显示进度条;

客户端:

# Author:q1.ang

import socket,os,json
import hashlib
import sys

class FtpClient(object):
    def __init__(self):
        self.client = socket.socket()
        self.account=‘‘
        self.path=‘‘

    def help(self):
        ‘‘‘
        帮助
        :return: none
        ‘‘‘
        msg=        ‘‘‘help:
        dir
        cd ../..
        new ..
        del ..
        re ..
        put ..
        get ..‘‘‘
        print(msg)

    def connect(self,ip,port):
        ‘‘‘
        连接
        :param ip:
        :param port:
        :return:
        ‘‘‘
        self.client.connect((ip,port))

    def authenticate(self):
        ‘‘‘
        用户登陆认证
        :return:auth真假
        ‘‘‘
        auth=False
        try_count=0
        while try_count<3:
            self.account=input(‘Account:‘).strip()
            password=input(‘Password:‘).strip()
            #获取账号密码的MD5值
            m=hashlib.md5()
            m.update((self.account+password).encode(‘utf-8‘))
            #发送acc+MD5
            self.client.send((self.account+‘ ‘+m.hexdigest()).encode(‘utf-8‘))
            #接收服务器的认证结果
            auth_recv=json.loads(self.client.recv(1024).decode())
            print(auth_recv[‘log res‘])
            if auth_recv[‘log res‘]==‘login success‘:
                auth=True
                print(‘desk size:‘,auth_recv[‘desk size‘])
                return auth
            try_count+=1
            if try_count==3:
                print(‘you have try 3 times...exit‘)
        else:
            return auth

    def interactive(self):
        ‘‘‘
        交互模块,调用各个功能,在子功能中与服务器实现收发
        :return:none
        ‘‘‘
        if self.authenticate(): #认证
            while True:
                cmd = input(‘>>>‘).strip()
                if len(cmd)==0:continue
                cmd_str=cmd.split()[0]
                if hasattr(self,‘cmd_%s‘%cmd_str):
                    func=getattr(self,‘cmd_%s‘%cmd_str)
                    func(cmd)
                else:
                    self.help()

    def cmd_dir(self,*args):
        ‘‘‘
        查看当面目录下文件
        :param args: dir没使用
        :return: none
        ‘‘‘
        msg_dic = {
            ‘action‘:‘dir‘
        }
        self.client.send(json.dumps(msg_dic).encode(‘utf-8‘))
        print(self.account,‘list:‘)
        server_respone = self.client.recv(1024).decode()
        for i in json.loads(server_respone):
            print(i)

    def cmd_cd(self,*args):
        ‘‘‘
        切换目录
        :param args: cd 目录名
        :return: none
        ‘‘‘
        cmd_split=args[0].split()
        if len(cmd_split)>1:
            if cmd_split[1][0:len(self.account)]==self.account:
                self.path = ‘\\‘+cmd_split[1][len(self.account)+1:]
            else:
                self.path += ‘\\‘+cmd_split[1]
            msg_dic = {
                ‘action‘: ‘cd‘,
                ‘path‘:self.path
            }
            print(msg_dic)
            self.client.send(json.dumps(msg_dic).encode(‘utf-8‘))
            auth_path=self.client.recv(1024).decode()

            if  auth_path== ‘True‘:
                print((self.account+‘:‘+self.path).replace(‘\\\\‘,‘\\‘))
            else:
                print(‘找不到指定的路径‘)
        else:
            print(‘you not write the folder name...‘)

    def cmd_new(self,*args):
        ‘‘‘
        新建目录
        :param args: cmd
        :return: new 目录名
        ‘‘‘
        cmd_split=args[0].split()
        if len(cmd_split)>1:
            foldername=cmd_split[1]
            msg_dic={
                ‘action‘:‘new‘,
                ‘foldername‘:foldername
            }
            self.client.send(json.dumps(msg_dic).encode(‘utf-8‘))
            recv=self.client.recv(1024).decode()
            print(recv)
        else:
            print(‘no name of the new file...‘)

    def cmd_del(self,*args):
        ‘‘‘
        删除目录或文件
        :param args:del 文件名
        :return: none
        ‘‘‘
        cmd_split=args[0].split()
        if len(cmd_split)>1:
            msg_dic={
                ‘action‘:‘del‘,
                ‘name‘:cmd_split[1]
            }
            self.client.send(json.dumps(msg_dic).encode(‘utf-8‘))
            recv=self.client.recv(1024).decode()
            print(recv)

        else:
            print(‘no name of the file...‘)

    def cmd_re(self,*args):
        ‘‘‘
        重命名
        :param args: re 文件名
        :return: none
        ‘‘‘
        cmd_split=args[0].split()
        if len(cmd_split)>1:
            new_name=input(‘new name:‘).strip()
            msg_dic={
                ‘action‘:‘re‘,
                ‘name‘:cmd_split[1],
                ‘new name‘:new_name
            }
            self.client.send(json.dumps(msg_dic).encode(‘utf-8‘))
            recv=self.client.recv(1024).decode()
            print(recv)
        else:
            print(‘the name of file or folder has not write..‘)

    def cmd_put(self,*args):
        ‘‘‘
        上传文件
        :param args: put 文件名
        :return: none
        ‘‘‘
        cmd_split=args[0].split()
        if len(cmd_split)>1:
            filename=cmd_split[1]
            if os.path.isfile(filename):
                filesize=os.stat(filename).st_size
                msg_dic = {
                    ‘action‘: ‘put‘,
                    ‘filename‘: filename,
                    ‘filesize‘: filesize,
                    ‘override‘: True
                }
                self.client.send(json.dumps(msg_dic).encode(‘utf-8‘))

                server_respone=self.client.recv(1024).decode()
                if server_respone==‘out of memory‘:
                    print(‘the mamory of your desk is not enough to save this file[%s(%d Mb)]‘ % (filename, filesize / 1048576))
                else:
                    l=0
                    sys.stdout.write(‘0%‘)
                    sys.stdout.flush()
                    with open(filename,‘rb‘) as f:
                    # f=open(filename,‘rb‘)
                        for line in f:
                            self.client.send(line)
                            l+=len(line)
                            if l>(filesize/20):
                                sys.stdout.write(‘>‘)
                                sys.stdout.flush()
                                l-=(filesize/20)
                        else:
                            print(‘100%\nfile upload success...‘)
                            save_sigle=self.client.recv(1024).decode()
                            print(save_sigle)
            else:
                print(filename,‘is not exit‘)

    def cmd_get(self,*args):
        ‘‘‘
        下载文件
        :param args: get 文件名
        :return: none
        ‘‘‘
        print(‘get‘)
        cmd_split=args[0].split()
        if len(cmd_split)>1:
            filename=cmd_split[1]
            msg_dic={
                ‘action‘: ‘get‘,
                ‘filename‘:filename
            }
            self.client.send(json.dumps(msg_dic).encode(‘utf-8‘))
            auth_recv=json.loads(self.client.recv(1024).decode())
            if auth_recv[‘file acc‘]==‘file exist‘:
                filesize=auth_recv[‘filesize‘]
                revc_size=0
                l=0
                sys.stdout.write(‘0%‘)
                sys.stdout.flush()
                self.client.send(b‘200‘)    #防粘包
                if os.path.isfile(filename):
                    filename=filename+‘.new‘
                with open(filename,‘wb‘)as f:
                    while revc_size<filesize:
                        recv=self.client.recv(1024)
                        f.write(recv)
                        revc_size+=len(recv)
                        l+=len(recv)
                        if l>(filesize/20):
                            sys.stdout.write(‘>‘)
                            sys.stdout.flush()
                            l-=(filesize/20)
                    else:
                        print(‘100%\nreceive done‘)
            else:
                print(auth_recv[‘file acc‘])
        else:
            print(‘error:not write filename...‘)

ftp=FtpClient()
ftp.connect(‘localhost‘,6666)
ftp.interactive()

服务器端:

# Author:q1.ang
import socketserver,json,os
import hashlib

class MyTCPHandler(socketserver.BaseRequestHandler):
    acc_path = ‘‘
    account =‘‘
    available_size=0
    data_dic={}
    def authenticate(self):
        ‘‘‘
        用户认证
        :return: auth真假
        ‘‘‘
        auth=False
        try_count = 0
        while try_count < 3:
            #接收客户端的账号密码
            account,recv_md5=self.request.recv(1024).decode().split()
            print(account,recv_md5)
            BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
            file_path=‘%s\conf\\accounts\%s‘%(BASE_DIR,account)
            if os.path.isfile(file_path):
                with open(file_path,‘r‘) as f:
                    # acc_data=json.load(f)
                    self.data_dic=json.load(f)
                    m=hashlib.md5()
                    m.update((self.data_dic[‘account‘]+self.data_dic[‘password‘]).encode(‘utf-8‘))
                    print(m.hexdigest())
                    if m.hexdigest()==recv_md5:
                        print(‘login success‘)
                        self.account=account
                        used_size = int(self.data_dic[‘desk size‘].split(‘/‘)[0])
                        all_size = int(self.data_dic[‘desk size‘].split(‘/‘)[1])
                        self.available_size = all_size - used_size

                        print(‘available_size‘,self.available_size)

                        msg_dic = {
                            ‘log res‘: ‘login success‘,
                            ‘desk size‘: ‘%dMb/%dMb‘%(used_size/1048576,all_size/1048576)
                        }
                        auth=True
                        try_count=3
                    else:
                        print(‘account or password error‘)
                        msg_dic={
                            ‘log res‘:‘account or password error‘,
                        }
            else:
                print(‘the account dose not exist..‘)
                msg_dic = {
                    ‘log res‘: ‘the account dose not exist..‘,
                }
            try_count+=1
            self.request.send(json.dumps(msg_dic).encode(‘utf-8‘))

        return auth

    def cmd_dir(self,*args):
        ‘‘‘
        查看目录下文件
        :param args: cmd_dic
        :return: none
        ‘‘‘
        print(self.acc_path)
        print(os.listdir(self.acc_path))
        self.request.send(json.dumps(os.listdir(self.acc_path)).encode(‘utf-8‘))

    def cmd_cd(self,*args):
        ‘‘‘
        切换目录
        :param args: cmd_dic
        :return: none
        ‘‘‘
        BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        self.acc_path = ‘%s\\conf\\data\\%s‘%(BASE_DIR,self.account)
        auth_path=‘False_path‘ #不能发空字节
        path=self.acc_path+args[0][‘path‘]
        print(‘地址:‘,path)
        if os.path.exists(path):
            self.acc_path=path
            auth_path=‘True‘
            print(‘path‘,self.acc_path)
        else:
            print(‘找不到指定的路径‘)
        self.request.send(auth_path.encode(‘utf-8‘))

    def cmd_new(self,*args):
        ‘‘‘
        在当前目录下新建目录
        :param args: cmd_dic
        :return: none
        ‘‘‘
        path=self.acc_path+‘\\‘+args[0][‘foldername‘]
        if os.path.exists(path):
            print(‘folder is exist..‘)
            msg=‘folder is exist..‘
        else:
            os.mkdir(path)
            print(‘创建成功‘)
            msg = ‘folder create success..‘
        self.request.send(msg.encode(‘utf-8‘))

    def cmd_re(self,*args):
        ‘‘‘
        在当前目录下重命名文件
        :param args: cmd_dic
        :return: none
        ‘‘‘
        name = self.acc_path + ‘\\‘ + args[0][‘name‘]
        new_name=self.acc_path + ‘\\‘ + args[0][‘new name‘]
        try:
            os.rename(name,new_name)
            msg=‘rename success‘
        except FileNotFoundError as e:
            msg=‘the folder is not exist...‘
            print(e)
        self.request.send(msg.encode(‘utf-8‘))

    def cmd_del(self,*args):
        ‘‘‘
        在当前目录下删除目录(空)或文件
        :param args: cmd_dic
        :return: none
        ‘‘‘
        path = self.acc_path + ‘\\‘ + args[0][‘name‘]
        if os.path.isfile(path):
            os.remove(path)
            msg=‘del success‘
        elif os.path.exists(path):
            try:
                os.rmdir(path)
                msg = ‘del success‘
            except OSError as e:
                print(e)
                msg=‘the folder is not empty...‘
        else:
            msg=‘file or folder is not exist...‘
        self.request.send(msg.encode(‘utf-8‘))

    def cmd_put(self,*args):
        ‘‘‘
        接收客户端文件
        :return:
        ‘‘‘
        cmd_dic=args[0]
        filename=cmd_dic[‘filename‘]
        filesize=cmd_dic[‘filesize‘]

        if filesize>self.available_size:
            self.request.send(‘out of memory‘.encode(‘utf-8‘))
        else:
            file_path=‘%s\\%s‘%(self.acc_path,filename)
            if os.path.isfile(file_path):
                f=open(file_path+‘.new‘,‘wb‘)
            else:
                f = open(file_path, ‘wb‘)
            self.request.send(b‘200 ok‘) #防粘包
            recv_size=0
            while recv_size< filesize:
                data=self.request.recv(1024)
                f.write(data)
                recv_size+=len(data)
            else:
                f.close()
                print(‘file [%s] has uploaded‘%filename)
                self.available_size -= filesize
                print(‘available_size2‘,self.available_size)
                self.request.send((‘server save success\navailable size:‘
                                   ‘%d Mb‘%(self.available_size/1048576)).encode(‘utf-8‘))
                #更新用户数据
                used_size=self.data_dic[‘desk size‘].split(‘/‘)[0]
                all_size=self.data_dic[‘desk size‘].split(‘/‘)[1]
                print(‘filesize‘,filesize)
                print(‘used_size‘,used_size)
                print(‘all_size‘,all_size)
                self.data_dic[‘desk size‘]=‘%d/%s‘%(int(used_size)+filesize,all_size)

                BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
                file_path = ‘%s\conf\\accounts\%s‘ % (BASE_DIR, self.account)
                print(file_path)
                with open(file_path,‘w‘) as f:
                    json.dump(self.data_dic,f)

    def cmd_get(self,*args):
        ‘‘‘
        发送给客户端文件
        :param args: cmd_dic
        :return: none
        ‘‘‘
        cmd_dic=args[0]
        filename=cmd_dic[‘filename‘]
        file_path=‘%s\\%s‘%(self.acc_path,filename)
        if os.path.isfile(file_path):
            filesize=os.stat(file_path).st_size
            msg_dic={
                ‘file acc‘:‘file exist‘,
                ‘filesize‘:filesize
            }
            self.request.send(json.dumps(msg_dic).encode(‘utf-8‘))
            self.request.recv(1024) #防粘包
            with open(file_path,‘rb‘)as f:
                for line in f:
                    self.request.send(line)
                else:
                    print(‘file send done‘)

        else:
            msg_dic = {‘file acc‘: ‘file[%s] is not exist...‘%filename}
            self.request.send(json.loads(msg_dic).encode(‘utf-8‘))

    def handle(self):
        ‘‘‘
        重构socketserver的handle(),用来主要的交互
        :return:
        ‘‘‘
        print(‘waiting...‘)
        if self.authenticate():
            BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
            self.acc_path = ‘%s\\conf\\data\\%s‘ % (BASE_DIR, self.account)
            while True:
                print(‘登录成功‘,self.account)
                try:
                    self.data=self.request.recv(1024).strip()
                    print(‘{} wrote‘.format(self.client_address[0]))
                    cmd_dic=json.loads(self.data.decode())
                    print(cmd_dic)
                    action=‘cmd_‘+cmd_dic[‘action‘]
                    if hasattr(self,action):
                        func=getattr(self,action)
                        func(cmd_dic)

                except ConnectionResetError as e:
                    print(‘ConnectionResetError‘,e)
                    break

if __name__==‘__main__‘:
    HOST,PORT=‘localhost‘,6666
    server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
    server.serve_forever()

原文地址:https://www.cnblogs.com/q1ang/p/9193232.html

时间: 2024-11-05 16:14:23

【小程序】支持多用户在线的FTP程序的相关文章

开发一个支持多用户在线的FTP程序

一,项目题目:开发一个支持多用户在线的FTP程序 二,项目要求: 1.用户加密认证 2.允许同时多用户登录 3.每个用户有自己的家目录 ,且只能访问自己的家目录 4.对用户进行磁盘配额,每个用户的可用空间不同 5.允许用户在ftp server上随意切换目录 6.允许用户查看当前目录下文件 7.允许上传和下载文件,保证文件一致性(md5) 8.文件传输过程中显示进度条 9.附加功能:支持文件的断点续传 三,注意事项: 基本要求. 完成1,2,3,5,6,7,8 实力选手. 完成 上条 及需求4

Python开发程序:支持多用户在线的FTP程序

作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目录下文件 允许上传和下载文件,保证文件一致性 文件传输过程中显示进度条 附加功能:支持文件的断点续传(仅下载) 程序 1.最最重要的readme: ### 作者介绍: * author:lzl ### 博客地址: * http://www.cnblogs.c

支持多用户在线的Ftp程序

一.要求 二.思路 三.代码 服务器端: # #!/usr/bin/env python # # -*- coding: utf-8 -*- import sys import time import socket import hashlib import pickle import subprocess import socketserver class Myserver(socketserver.BaseRequestHandler): def recv_file(self): conn=

python 开发一个支持多用户在线的FTP

### 作者介绍:* author:lzl### 博客地址:* http://www.cnblogs.com/lianzhilei/p/5813986.html### 功能实现 作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目录下文件 允许上传和下载文件,保证文件一致性 文件传输过程中显示进度条 附加功能

python之FTP程序(支持多用户在线)

转发注明出处:http://www.cnblogs.com/0zcl/p/6259128.html,这次博客写了很久~~ 一.需求 1. 用户加密认证 (完成)2. 允许同时多用户登录 (完成)3. 每个用户有自己的家目录 ,且只能访问自己的家目录(完成)4. 对用户进行磁盘配额,每个用户的可用空间不同(完成)5. 允许用户在ftp server上随意切换目录cd(完成)6. 允许用户查看当前目录下文件ls(完成)7. 允许上传put和下载get文件(完成),保证文件一致性(此需求不做)8. 文

python 多用户在线的FTP程序

要求: 1.用户加密认证 2.允许同时多用户登录 3.每个用户有自己的家目录 ,且只能访问自己的家目录 4.对用户进行磁盘配额,每个用户的可用空间不同 5.允许用户在ftp server上随意切换目录 6.允许用户查看当前目录下文件 7.允许上传和下载文件,保证文件一致性 8.文件传输过程中显示进度条 9.附加功能:支持文件的断点续传 README: 设计说明 1.client连接server端需要验证账号密码,密码使用MD5加密传输. 2.用户信息保存在本地文件中,密码MD5加密存储.磁盘配额

【python练习】基于socket的FTP程序 v1.1.0(支持并发)

增加功能 1.在FTP(1.0.0)的基础上,支持了多并发的功能 2.允许配置最大并发数,比如允许只有10个并发用户 程序功能: 本程序模拟实现了一个FTP程序: 1.程序分为客户端和服务端 2.用户可以登录和注册账号,登录密码有MD5加密 3.每个用户有自己的家目录 ,且只能访问自己的家目录 4.用户可以随意切换目录(仅限自己的家目录) 5.允许用户查看当前目录下文件 6.允许上传和下载文件,保证文件一致性(md5),(不允许下载/上传文件夹,会出现不可恢复bug,用户配置文件需要重置.时间原

FTP程序

需求:开发一个支持多用户同时在线的FTP程序 要求:1.用户加密认证2.允许同时多用户登录(用到并发编程的知识,选做)3.每个用户有自己的家目录,且只能访问自己的家目录4.对用户进行磁盘配额,每个用户的可用空间不同(选做)5.允许用户在ftp server上随意切换目录6.允许用户查看当前目录下的文件7.允许上传和下载文件,并保证文件的一致性8.文件传输过程中显示进度条9.附加:支持文件的断点续传(选做)开发的程序需符合PEP8开发规范,及专业的生产软件设计规范,包括目录.代码命名.功能接口等

yunBT:一个基于TP3.1的多用户BT离线下载程序,支持在线播放

说明:yunBT这个项目其实很早就有了,只是老没更新,现在作者基于ThinkCMS重做该程序,支持多用户注册下载,Magnet和HTTP下载.每个单独用户支持10个任务,默认下载文件最大为10GB,可以在后台修改.下载完成后用户可以直接查看下载的文件仅支持mp4文件在线播放.管理员可以添加用户的下载量及查看管理下载任务. 由于该程序刚出来,功能较少,暂不支持下载工具下载,可以在浏览器中下载,后续将添加,而且作者计划以后会增加分享功能.用户转码功能.积分功能.邀请功能.工具下载.使用Onedriv