首页 > 其他分享 >FTP项目代码

FTP项目代码

时间:2024-08-21 08:53:09浏览次数:6  
标签:__ FTP 项目 data 代码 path import os self

直接上代码吧

整个程序包目录结构如下:

FTP:
  ftp_client
      client.py

  ftp_server
      bin
         start_server.py
      conf
         settings.py
      core
          main.py
          server.py
      home
          jack
      logger

ftp_server
1.start_server.py

import os,sys
PATH=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(PATH)
from core import main

if __name__ == '__main__':
    main.ArgvHandler()

2.main.py

import optparse
import socketserver
import os
BASEPATH=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
from conf import settings
from core import server

class ArgvHandler():
    def __init__(self):
        self.op=optparse.OptionParser()
        options,args=self.op.parse_args()
        self.verification(options,args)

    def verification(self,options,args):
        if hasattr(self,args[0]):
            func=getattr(self,args[0])
            func()

    def start(self):
        s=socketserver.ThreadingTCPServer((settings.IP,settings.PORT),server.Myserver)
        print('服务端开始运行...')
        s.serve_forever()

    def stop(self):
        pass

3.server.py

import socketserver
import json
import os
user_pwd={
    'username':'jack',
    'password':'123'
}

class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            data=self.request.recv(1024).decode('utf-8')
            data=json.loads(data)
            #拿到了字典
            if hasattr(self,data['action']):
                func=getattr(self,data['action'])
                func(**data)

    def put(self,**data):
        filesize=data['filesize']
        filepath=os.path.join(data['targetpath'],data['filename'])
        has_size=0
        if os.path.exists(filepath):
            now_has_size=os.stat(filepath).st_size
            if now_has_size < filesize:
                 #断点续传
                self.request.sendall('please_choice'.encode('utf-8'))
                choice=self.request.recv(1024).decode('utf-8')
                if choice == 'Y':
                    self.request.sendall(str(now_has_size).encode('utf-8'))
                    has_size+=now_has_size
                    f=open(filepath,'ab')
                else:
                    f = open(filepath, 'wb')
            else:
                self.request.sendall('ok'.encode('utf-8'))
        else:
            self.request.sendall('ready'.encode('utf-8'))
            f=open(filepath,'wb')

        while has_size < filesize:
            try:
                file_data=self.request.recv(1024)
            except Exception as e:
                break
            f.write(file_data)
            has_size+=len(file_data)
        f.close()

    def auth(self,**data):
        if data['username'] == user_pwd['username'] and data['password'] == user_pwd['password']:
            self.request.sendall('101'.encode('utf-8'))
        else:
            self.request.sendall('102'.encode('utf-8'))

4.settings.py

IP='127.0.0.1'
PORT=8080

ftp_client

1.client.py
import socket
import optparse
import sys,os
import json
import time
BASEPATH=os.path.dirname(os.path.abspath(__file__))
ServerPath=os.path.join(os.path.dirname(BASEPATH),'ftp_server')
FilePath=os.path.join(BASEPATH,'a.txt')
ip_port=('127.0.0.1',8080)

class Myclient:
    def __init__(self):
        self.op=optparse.OptionParser()
        self.op.add_option("-s","--server",dest="server")
        self.op.add_option("-P", "--port", dest="port")
        self.op.add_option("-u", "--username", dest="username")
        self.op.add_option("-p", "--password", dest="password")
        self.options,self.args=self.op.parse_args()
        self.verity_port(self.options,self.args)
        self.connection()

    def verity_port(self,options,args):
        port=options.port
        if int(port)>0 and int(port)<65535:
            return True
        else:
            exit('端口不合法')
    def connection(self):
        print('客户端连接成功...')
        self.sock=socket.socket()
        self.sock.connect(ip_port)

    def auth(self):
        if self.authenticate():
            while True:
                cmd_msg=input('[%s]:' %self.user).strip()
                if not cmd_msg:continue
                if cmd_msg == 'quit':break
                cmd_list=cmd_msg.split()
                if hasattr(self,cmd_list[0]):
                    func=getattr(self,cmd_list[0])
                    func(*cmd_list)

    def put(self,*cmd_list):
        cmd_name,localfile,targetpath=cmd_list
        targetpath=os.path.join(ServerPath, 'home', self.user)
        filesize=os.stat(FilePath).st_size
        cmd_data={
            'action':cmd_name,
            'filename':localfile,
            'filesize':filesize,
            'targetpath':targetpath
        }
        # print(cmd_data['filename'],type(filesize),cmd_data['targetpath'])
        self.sock.sendall(json.dumps(cmd_data).encode('utf-8'))
        confirm_msg=self.sock.recv(1024).decode('utf-8')
        has_send=0
        if confirm_msg == 'ok':
            print('文件已存在,不需要上传了...')
            return
        elif confirm_msg == 'ready':
            print('开始全量上传...')
        elif confirm_msg == 'please_choice':
            choice=input('选择增量[y]还是全量[n]:[Y/N]').upper()
            if choice == 'Y':
                self.sock.sendall(choice.encode('utf-8'))
                choice_msg=self.sock.recv(1024).decode('utf-8')
                print('开始断点续传...')
                has_send = int(choice_msg)
            else:
                self.sock.sendall(choice.encode('utf-8'))
                print('开始整包覆盖...')

        f=open(FilePath, 'rb')
        f.seek(has_send)
        while has_send < filesize:
            file_data=f.read(1)
            self.sock.sendall(file_data)
            has_send+=len(file_data)
            self.show_process(has_send, filesize)
        f.close()
        print('传输结束')
        return
    def show_process(self,has,total):
        procent=int((has/total)*100)

        # print(procent)
        # sys.stdout.write('%s%%')
        sys.stdout.write('\r%s%% %s' %(procent,'#'*procent))
        time.sleep(0.1)
        sys.stdout.flush()

    def authenticate(self):
        username=self.options.username
        password=self.options.password
        if username is None or password is None:
            username=input('username:').strip()
            password=input('password:').strip()
            return self.verify_login(username, password)
        return self.verify_login(username,password)

    def verify_login(self,user,pwd):
        login_data={
            'action':'auth',
            'username':user,
            'password':pwd
        }
        login_data=json.dumps(login_data)
        self.sock.sendall(login_data.encode('utf-8'))
        verify_login_result=self.sock.recv(1024).decode('utf-8')
        if verify_login_result  == '101':
            self.user=user
            print('登录成功')
            return True
        else:
            print('用户名或密码错误,请重新输入!')
            return self.authenticate()


mc=Myclient()
mc.auth()

上面这段代码基本实现了登录验证、上传文件(整包上传和断点续传)以及进度条,但是不够完善,有些bug,比如重复执行put a.txt jack的命令会报错。
我没有找到为啥会这个样子,有待以后再找bug了。或者如有高手,请予赐教!

标签:__,FTP,项目,data,代码,path,import,os,self
From: https://www.cnblogs.com/kkbest/p/18369987

相关文章

  • 排序算法 排序性能测试代码(随机数调整,高精度时间) - C++
    目录测试工具源码testsort测试工具C++11标准库<chrono>中高精度计时器,时间精度可以达到1纳秒.C++11标准库<random>中随机数生成器,可以实现各类随机数,本测试主要用于实现9成随机数下排序性能源码源码我拆分成两部分,一部分为测试,一部分为sort源码.合并一起使用test......
  • java项目部署到linux
    手工部署打包获取打包的jar包将jar包放到linux中(可通过xftp软件)的usr/local/ruiji执行jar包java-jarjar包名称指定端口:java-jarjar包名称--server.port=端口号如果端口被占用,查看端口号命令netstat-tuln|grep:8080根据端口号杀死进程lsof-i:8......
  • 计算机毕业设计-基于Python+Django的基于知识图谱的医疗问答系统项目开发实战(附源码+
    大家好!我是程序员一帆,感谢您阅读本文,欢迎一键三连哦。......
  • 计算机毕业设计-基于Python+Flask的基于深度学习的电影评论情感分析系统项目开发实战(
    大家好!我是程序员一帆,感谢您阅读本文,欢迎一键三连哦。......
  • 线性表小项目(通讯录、贪吃蛇)
    目录通讯录新增联系人 查找联系人 删除联系人修改联系人 贪吃蛇小游戏Win32APIGetStdHandleGetConsoleCursorInfoCONSOLE_CURSOR_INFO SetConsoleCursorInfoSetConsoleCursorPosition GetAsyncKeyState 宽字符介绍贪吃蛇游戏设计游戏开始阶段场景打印:......
  • MIKroTIK wireguard 在阿里云与云下路由器项目记录
    一、项目背景:公司所有服务器都在阿里云上,需要内网互通。二、项目调研:市场上sd-wan大多分为2派(关于协议之间的对比可再出一个文章进行讨论):1、华为、思科等代表传统利用:Gre,Ipsec,SRv6等数通派(RFC)协议。其特点是:稳定性很好,设备厂家支持广泛无需厂家内部二次适配新协议。2、腾讯......
  • 代码随想录Day21
    669.修剪二叉搜索树给你二叉搜索树的根节点root,同时给定最小边界low和最大边界high。通过修剪二叉搜索树,使得所有节点的值在[low,high]中。修剪树不应该改变保留在树中的元素的相对结构(即,如果没有被移除,原有的父代子代关系都应当保留)。可以证明,存在唯一的答案。所......
  • 线程(Thread)的使用方法和锁(同步代码块,lock锁)的问题
    多线程:    进程:      正在运行的程序,是系统进行资源分配和调用的独立单位。      每一个进程都有它自己的内存空间和系统资源。      理解:一个正在运行的软件    线程:      是进程中的单个顺序控制流,是......
  • Swift代码重构:提升代码质量的魔法工具
    标题:Swift代码重构:提升代码质量的魔法工具Swift是一种用于iOS、macOS、watchOS和tvOS应用开发的强类型、编译型编程语言。随着应用的迭代和功能的增加,代码的维护和扩展变得越来越复杂。Swift的代码重构工具可以帮助开发者改进现有代码的设计而不改变其外部行为,从而提高代码......
  • 在 React 项目中 Editable Table 的实现
    在React项目中EditableTable的实现 我们是袋鼠云数栈UED团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。本文作者:佳岚可编辑表格在数栈产品中是一种比较常见的表单数据交互方式,一般都支持动态的新增、删......