python之路——作业:开发简单的FTP

一、作业要求

开发简单的FTP:
1. 用户登陆
2. 上传/下载文件
3. 不同用户家目录不同
4. 查看当前目录下文件
5. 充分使用面向对象知识

二、程序目录说明

FTP/
|-- FTPClient/              #客户端文件夹
|   |-- 示例文件夹/         #客户端上传/下载示例文件夹
|   |-- Client_start.py     #客户端启动程序
|
|-- FTPServer/              #服务端文件夹
|   |-- bin/
|   |   |-- __init__.py
|   |   |-- Server_start.py   #程序启动的主入口
|   |
|   |-- conf/
|   |   |-- setting.py         #配置文件
|   |
|   |-- db/                    #用户数据
|   |   |-- alex               #用户名alex的数据文件夹
|   |   |-- japhi              #用户名japhi的数据文件夹
|   |
|   |-- home/
|   |   |-- alex/               #用户alex用户家目录
|   |   |-- japhi/              #用户japhi用户家目录
|   |
|-- log/
|   |-- log_sys.log             #日志文件(未启用)
|
|-- src/
|   |-- __init__.py
|   |-- common.py               #公共功能
|   |-- Server_start.py         #程序启动的主入口
|   |-- user.py                 #用户类及方法
|
|-- FTP.png                     #流程图
|-- README.txt

三、流程图

四、作业代码

1、FTPClient客户端文件夹下客户端启动程序Client_start.py:

import socket,os,sys,time
Basedir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),"FTPServer")
updir = os.path.join(os.path.dirname(os.path.abspath(__file__)),"示例文件夹")
sys.path.append(Basedir)
from conf import settings

def upload(client,user_info,name):
    ‘‘‘
    客户端上传文件的函数
    :param client:scoket客户端标志
    :param user_info:客户端登陆用户的信息
    :param name:客户端登陆用户的名字
    :return:none
    ‘‘‘
    print("\033[1;37m当前可选上传\033[0m".center(40,"*"))
    dic = {}
    for root, dirs, files in os.walk(updir):
        for i,j in enumerate(files):
            k = i+1
            dic[k] = j
            print("\033[1;37m%s:%s\033[0m"%(k,j))
    choice = input("请输入要上传的文件序号:>>>")
    command = "upload+"+user_info+"+"+dic[int(choice)]
    client.sendall(bytes(command,encoding="utf-8"))
    res = client.recv(1024)
    if str(res,encoding="utf-8") == "True":
        dir = os.path.join(updir,dic[int(choice)])
        with open(dir,"rb") as f:
            data = f.read()
            a = str(len(data))
            client.sendall(bytes(a,encoding="utf-8"))
            client.sendall(data)
            time.sleep(0.5)
            print("\033[1;37m文件上传成功\033[0m")

def download(client,user_info,name):
    ‘‘‘
    客户端下载文件的函数
    :param client: scoket客户端标志
    :param user_info: 客户端登陆的用户信息
    :param name:客户端登陆的用户名字
    :return: none
    ‘‘‘
    dic = {}
    command = "download+"+user_info
    client.sendall(bytes(command, encoding="utf-8"))
    data = client.recv(4069)
    res = eval(str(data, encoding="utf-8"))
    if len(res) == 0:
        print("\033[1;31m当前目录下暂无文件\033[0m".center(40, "-"))
    else:
        for i,j in enumerate(res):
            k = i + 1
            dic[k] = j
            print("\033[1;37m%s:%s\033[0m" % (k, j))
        choice = input("请选择要下载的文件序号:>>>")
        cm = "downloadfile+"+dic[int(choice)]+"+"+name
        client.sendall(bytes(cm, encoding="utf-8"))
        print("\033[1;37m准备开始下载文件\033[0m")
        dir = os.path.join(updir, dic[int(choice)])
        res_length = str(client.recv(1024).decode())
        length = 0
        with open(dir, "wb") as f:
            while True:
                data = client.recv(1024)
                length += len(data)
                f.write(data)
                if  length >= int(res_length):
                    print("\033[1;37m文件下载成功\033[0m")
                    time.sleep(0.5)
                    break

def view_file(client,user_info,name):
    ‘‘‘
    客户端查看当前目录下文件的函数
    :param client: scoket客户端标志
    :param user_info: 客户端登陆的用户信息
    :param name: 客户端登陆的用户名字
    :return: none
    ‘‘‘
    command = "view+"+user_info
    client.sendall(bytes(command,encoding="utf-8"))
    data = client.recv(1024)
    res = eval(str(data,encoding="utf-8"))
    if len(res) == 0:
        print("\033[1;31m当前目录下暂无文件\033[0m".center(40, "-"))
    else:
        for i in res:
            print("\033[1;35m%s\033[0m"%i)

def operate(client,user_info,name):
    ‘‘‘
    客户端操作主函数
    :param client: scoket客户端标志
    :param user_info: 客户端登陆的用户信息
    :param name: 客户端登陆的用户名字
    :return: none
    ‘‘‘
    dic = {"1":upload,"2":download,"3":view_file}
    info = ‘‘‘------操作指令------
    1、上传文件
    2、下载文件
    3、查看目录下文件
    4、退出
    ‘‘‘
    while True:
        print("\033[1;33m%s\033[0m" % info)
        choice = input("请输入你要操作的命令:>>>").strip()
        if choice.isdigit() and 0 < int(choice) <= len(dic):
            dic.get(choice)(client,user_info,name)
        elif int(choice) == 4:
            break
        else:
            print("\033[1;31m输出错误\033[0m".center(40, "-"))

def com_parse(client,com):
    ‘‘‘
    客户端用户登陆注册命中解析函数
    :param client: 客户端scoket标志
    :param com: 命令
    :return: 登陆成功返回True,否则False
    ‘‘‘
    # print(com)
    client.sendall(bytes(com,encoding="utf-8"))
    re = client.recv(4096)
    if str(re,encoding="utf-8") == "Success":
        return True
    elif str(re, encoding="utf-8") == "Success":
        return False

def login(client,data):
    ‘‘‘
    客户端用户登陆函数
    :param client: 客户端scoket标志
    :param data: 数据
    :return: none
    ‘‘‘
    name = input("请输入您的名字:>>>").strip()
    psd = input("请输入密码:>>>").strip()
    user_info = name+"+"+psd
    com = "login+"+user_info
    if com_parse(client,com):
        operate(client,user_info,name)
    else:
        print("\033[1;31m登陆出现异常\033[0m")

def register(client,data):
    ‘‘‘
    客户端用户注册函数
    :param client: 客户端scoket标志
    :param data: 数据
    :return: none
    ‘‘‘
    name = input("请输入您的名字:>>>").strip()
    psd = input("请输入密码:>>>").strip()
    com = "register+" + name + "+" + psd
    if com_parse(client, com):
        user_info = name + "+" + psd
        print("\033[1;31m注册成功\033[0m")
        command = "view+" + user_info
        client.sendall(bytes(command, encoding="utf-8"))
        res1 = client.recv(1024)
        operate(client, user_info, name)
    else:
        print("\033[1;31m注册出现异常\033[0m")

def quit(client,data):
    ‘‘‘
    程序退出函数
    :param client: 客户端scoket标志
    :param data: 用户数据
    :return: none
    ‘‘‘
    exit()

def main_func(client,data):
    ‘‘‘
    客户端主菜单函数
    :param client: 客户端scoket标志
    :param data: 数据
    :return: none
    ‘‘‘
    dic = {"1":login,"2":register,"3":quit}
    info = ‘‘‘------用户登录界面------*{0}*
        1、登陆
        2、注册
        3、退出
    ‘‘‘.format(str(data,encoding="utf-8"))
    print("\033[1;33m%s\033[0m"%info)
    what = input("你要干嘛?>>>").strip()
    if what.isdigit() and 0 < int(what) <= len(dic):
        dic.get(what)(client,data)
    else:
        print("\033[1;31m输出错误\033[0m".center(40,"-"))

if __name__ == ‘__main__‘:
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    client.connect(("localhost",settings.PORT))
    main_func(client,client.recv(1024))
    client.close()

2、FTPServer服务端文件下conf文件下配置程序settings.py:

import os

basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
user_home = "%s/home"%basedir
user_info = "%s/db"%basedir

HOST = "0.0.0.0"
PORT = 9999

3、FTPServer服务端文件下src文件下公共功能程序common.py:

import logging,os,pickle,sys,uuid
frame = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(frame)
# from conf import setting
#
# def sys_logging(content,levelname):
#     ‘‘‘
#     程序记录日志函数
#     :param content: 日志的内容
#     :param levelname: 日志的等级
#     :return: none
#     ‘‘‘
#     _filename = os.path.join(setting.log_dir,"log_sys.log")
#     log = logging.getLogger(_filename)
#     logging.basicConfig(filename=_filename,level=logging.INFO,format=‘%(asctime)s-%(levelname)s-%(message)s‘, datefmt=‘%m/%d/%Y %I:%M:%S %p‘)
#     if levelname == ‘debug‘:
#         logging.debug(content)
#     elif levelname == ‘info‘:
#         logging.info(content)
#     elif levelname == ‘warning‘:
#         logging.warning(content)
#     elif levelname == ‘error‘:
#         logging.error(content)
#     elif levelname == ‘critical‘:
#         logging.critical(content)

def show(msg,msg_type):
    ‘‘‘
    程序不同信息打印的字体颜色
    :param msg: 打印信息
    :param msg_type: 打印信息的类型
    :return: none
    ‘‘‘
    if msg_type == "info":
        show_msg = "\033[1;35m%s\033[0m"%msg
    elif msg_type == "error":
        show_msg = "\033[1;31m%s\033[0m"%msg
    elif msg_type == "msg":
        show_msg = "\033[1;37m%s\033[0m"%msg
    else:
        show_msg = "\033[1;32m%s\033[0m"%msg
    print(show_msg)

   src文件夹下Server_start.py服务端启动主函数:

import socket,os,sys
Base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(Base_dir)
from conf import settings
from common import show
from user import User

def fuck_tcp(con,addr):
    ‘‘‘
    服务端数据解析主函数
    :param con:
    :param addr:
    :return:
    ‘‘‘
    show("收到{0}的连接请求,正在通信中。。。".format(addr),"info")
    con.sendall(bytes("连接成功",encoding="utf-8"))
    while True:
        cmd = con.recv(4096)
        if not cmd:
            break
        else:
            # try:
            data = str(cmd.decode(encoding="utf-8"))
            res = data.split("+")
            if res[0] == "login":
                show("收到客户端登陆的请求,正在登陆。。。", "msg")
                name = res[1]
                psd = res[2]
                user = User(name, psd)
                sign = user.login()
                if sign:
                    con.sendall(bytes("Success", encoding="utf-8"))
                else:
                    con.sendall(bytes("Failure", encoding="utf-8"))
            elif res[0] == "register":
                show("收到客户端注册的请求,正在注册。。。", "msg")
                name = res[1]
                psd = res[2]
                user = User(name, psd)
                if user.register():
                    con.sendall(bytes("Success", encoding="utf-8"))
                else:
                    con.sendall(bytes("Failure", encoding="utf-8"))
            elif res[0] == "view":
                show("收到客户端创建或查看当前目录文件的请求。。。", "msg")
                name = res[1]
                psd = res[2]
                user = User(name, psd)
                res = user.view_file()
                file = str(res)
                con.sendall(bytes(file, encoding="utf-8"))
                show("当前目录文件查看或创建成功", "info")
            elif res[0] == "upload":
                show("收到客户端上传文件的请求。。。", "msg")
                name = res[1]
                filename = res[3]
                con.sendall(bytes("True",encoding="utf-8"))
                res_length = str(con.recv(1024).decode())
                User.receive(filename,name,res_length,con)
            elif res[0] == "download":
                show("收到客户端下载文件的请求。。。", "msg")
                name = res[1]
                psd = res[2]
                user = User(name, psd)
                res = user.view_file()
                file = str(res)
                con.sendall(bytes(file, encoding="utf-8"))
            elif res[0] == "downloadfile":
                show("开始下载文件", "msg")
                User.download_file(res[1], res[2], con)
                show("文件下载成功", "info")

if __name__ == ‘__main__‘:
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.bind(("localhost",settings.PORT))
    server.listen(5)
    show("正在监听[%s]地址[%s]端口,等待连接。。。"%(settings.HOST,settings.PORT),"info")
    con,addr = server.accept()
    fuck_tcp(con,addr)

    src文件下用户类程序user.py:

import os,sys,pickle,socket,time
Base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(Base_dir)
from conf import settings
from common import show

class User(object):
    ‘‘‘
    用户类
    ‘‘‘
    def __init__(self,username,psd):
        self.name = username
        self.password = psd
        self.home_path = settings.user_home + "/" +self.name

    def login(self):
        ‘‘‘
        用户登陆方法
        :return:
        ‘‘‘
        user_dic = User.info_read(self.name)
        if user_dic.get(self.name) == self.password:
            show("登陆成功","info")
            return True
        else:
            show("登陆失败,用户名或密码错误","error")
            return False

    def register(self):
        ‘‘‘
        用户注册方法
        :return:
        ‘‘‘
        dic = {}
        dic[self.name] = self.password
        if User.info_write(self.name,dic):
            show("注册成功","info")
            return True
        else:
            show("注册失败","error")
            return False

    def view_file(self):
        ‘‘‘
        查看当前目录下文件
        :return: 目录下文件名组成的列表
        ‘‘‘
        if not os.path.exists(self.home_path):
            os.mkdir(self.home_path)
            with open("%s\空白文件"%self.home_path,"w") as f:
                f.write("空白文件")
        for root, dirs, files in os.walk(self.home_path):
            return files

    @staticmethod
    def download_file(filename,name,con):
        ‘‘‘
        下载文件静态方法
        :param filename: 文件名
        :param name: 用户名
        :param con: 标志
        :return: none
        ‘‘‘
        dir = os.path.join(os.path.join(os.path.join(Base_dir, "home"), name), filename)
        with open(dir,"rb") as f:
            # while True:
            data = f.read()
            a = str(len(data))
            # print(type(a))
            con.sendall(bytes(a,encoding="utf-8"))
            con.sendall(data)

    @staticmethod
    def receive(filename,name,res_length,con):
        ‘‘‘
        接收文件静态方法
        :param filename: 文件名
        :param name: 用户名
        :param con: 标志
        :return: none
        ‘‘‘
        dir = os.path.join(os.path.join(os.path.join(Base_dir,"home"),name),filename)
        length = 0
        f =  open(dir, "wb")
        while True:
            data = con.recv(1024)
            length += len(data)
            f.write(data)
            # print(length)
            if length == int(res_length):
                show("文件下载成功","info")
                f.flush()
                f.close()
                return True

    @staticmethod
    def info_read(name):
        ‘‘‘
        读取用户数据的静态方法
        :param name: 用户名
        :return: 字典
        ‘‘‘
        user_dir = os.path.join(settings.user_info,name)
        if os.path.exists(user_dir):
            with open(user_dir,"rb") as f:
                dic = pickle.load(f)
                return dic
        else:
            print("用户数据为空")

    @staticmethod
    def info_write(name,dic):
        ‘‘‘
        写入用户数据的静态方法
        :param name:用户名
        :param dic:用户信息字典
        :return:True
        ‘‘‘
        user_dir = os.path.join(settings.user_info, name)
        with open(user_dir,"wb") as f:
            pickle.dump(dic,f)
            return True

五、程序界面说明

 

时间: 2024-11-06 23:16:37

python之路——作业:开发简单的FTP的相关文章

Python之路,Day18 - 开发一个WEB聊天来撩妹吧

Python之路,Day18 - 开发一个WEB聊天来撩妹吧 本节内容: 项目实战:开发一个WEB聊天室 功能需求: 用户可以与好友一对一聊天 可以搜索.添加某人为好友 用户可以搜索和添加群 每个群有管理员可以审批用户的加群请求,群管理员可以用多个,群管理员可以删除.添加.禁言群友 可以与聊天室里的人进行临时会话(与qq群一样) 可以在群中发图片 可以与好友一对一发文件 知识必备: django html\css\js bootstrap jquery, ajax 前景介绍 首先我们知道http

python之路——作业:Select FTP(仅供参考)

一.作业需要 使用SELECT或SELECTORS模块实现并发简单版FTP允许多用户并发上传下载文件 二.README 程序实现了以下功能: 1.用户登录注册(测试用户:japhi.alex:密码都是123) 2.上传/下载文件(已有示例文件) 3.查看不同用户自己家得目录下文件 4.使用了selector模块,实现单线程下并发效果 客户端启动程序:Client_start.py 服务端启动程序:Server_start.py 三.目录说明 Select FTP/ |-- Select FTPC

python之路——作业:高级FTP(仅供参考)

一.作业需求 1. 用户加密认证2. 多用户同时登陆3. 每个用户有自己的家目录且只能访问自己的家目录4. 对用户进行磁盘配额.不同用户配额可不同5. 用户可以登陆server后,可切换目录6. 查看当前目录下文件7. 上传下载文件,保证文件一致性8. 传输过程中现实进度条9.支持断点续传 二.实现功能 1.多用户同时登录注册(已有用户:japhi.alex:密码都是123)2.上传/下载文件(已有示例文件)3.查看不同用户自己家得目录下文件,且只能访问自己的家目录4.对用户进行磁盘配额,不同用

Python07新版作业源码:开发简单的FTP(仅供参考)

服务器端:server_server.py 1 #!usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # auther:Mr.chen 4 # 描述: 5 6 import socket 7 import os 8 import threading 9 import time 10 import json 11 from user_users import PersonInfo 12 13 DIR = os.path.dirname(os.path.ab

python之路——作业:类Farbic主机管理程序(仅供参考)

一.作业需求 1. 运行程序列出主机组或者主机列表2. 选择指定主机或主机组3. 选择让主机或者主机组执行命令或者向其传输文件(上传/下载)4. 充分使用多线程或多进程5. 不同主机的用户名密码.端口可以不同 二.实现功能 1.创建主机2.运行程序列出主机列表3.选择指定主机或主机组4.选择让主机或主机组执行命令或传输文件5.充分使用多线程注意:新用户使用本程序1.创建主机------->需根据自己现已开启的主机创建主机,将主机信息以文件的形式保存下来: 2.连接主机------->根据用户创

Python开发简单记事本

摘要: 本文是使用Python,结合Tkinter开发简单记事本. 本文的操作环境:ubuntu,Python2.7,采用的是Pycharm进行代码编辑,个人很喜欢它的代码自动补齐功能. 最近很想对python加深学习一下,同时也是想试着做一些东西,今天使用python,结合Tkinter来做一个简单的跨平台记事本.最终实现的记事本如下,也算是麻雀虽小,五脏俱全了,之后也是会继续完善的: 如上图,我们可以看到这个记事本主要分为三个模块:文件,编辑和关于,结合我自身的习惯外加四个toolbar:新

Python之路,Day20 - 分布式监控系统开发

Python之路,Day20 - 分布式监控系统开发 本节内容 为什么要做监控? 常用监控系统设计讨论 监控系统架构设计 监控表结构设计 为什么要做监控? –熟悉IT监控系统的设计原理 –开发一个简版的类Zabbix监控系统 –掌握自动化开发项目的程序设计思路及架构解藕原则 常用监控系统设计讨论 Zabbix Nagios 监控系统需求讨论 1.可监控常用系统服务.应用.网络设备等 2.一台主机上可监控多个不同服务.不同服务的监控间隔可不同 3.同一个服务在不同主机上的监控间隔.报警阈值可不同

小白学习Python之路---开发环境的搭建

本节内容 1.Python的介绍 2.发展史 3.安装Python 4.搭建开发环境 5.Hello World程序 一.Python的介绍 Python的创始人为荷兰人吉多·范罗苏姆(Guido van Rossum).1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,作为ABC 语言的一种继承.之所以选中Python(大蟒蛇的意思)作为该编程语言的名字,是取自英国20世纪70年代首播的电视喜剧<蒙提.派森干的飞行马戏团>(Monty Pyth

七日Python之路--第十二天(Django Web 开发指南)

<Django Web 开发指南>.貌似使用Django1.0版本,基本内容差不多,细读无妨.地址:http://www.jb51.net/books/76079.html (一)第一部分 入门 (1)内置数字工厂函数 int(12.34)会创建一个新的值为12的整数对象,而float(12)则会返回12.0. (2)其他序列操作符 连接(+),复制(*),以及检查是否是成员(in, not in) '**'.join('**')   或  '***%s***%d' % (str, int)