python文件传输库,python 基于selectors库实现文件上传与下载

2023-05-16

server.py

import selectors

import socket

import os

import time

BASE_DIR =os.path.abspath(os.path.dirname(__file__))

class selectFtpserver:

def __init__(self):

self.dic = {} # 创建空字典

self.hasReceived = 0

self.hasSend=0

self.sel = selectors.DefaultSelector() # 生成一个select对象

self.create_socket() #create_socket()是创建socket对象函数完成绑定功能

self.hanle() #handle()函数完成循环监听

def create_socket(self):

sock = socket.socket()

sock.bind(('127.0.0.1', 8899))

sock.listen()

sock.setblocking(False)

self.sel.register(sock, selectors.EVENT_READ, self.accept) # 把刚生成的sock连接对象注册到select连接列表中,并交给accept函数处理

print("服务端已打开,请连接客户端")

def hanle(self):

while True:

events = self.sel.select() # 默认是阻塞,有活动连接就返回活动的连接列表

# 这里看起来是select,其实有可能会使用epoll,如果你的系统支持epoll,那么默认就是epoll

# print("event==",events)

for key, mask in events:

callback = key.data # 去调accept函数

callback(key.fileobj, mask) # key.fileobj就是readable中的一个socket连接对象

def accept(self,sock, mask):

conn, addr = sock.accept() # Should be ready

print('accepted', conn, 'from', addr)

conn.setblocking(False) # 设定非阻塞

self.sel.register(conn, selectors.EVENT_READ, self.read) # 新连接注册read回调函数

self.dic[conn] = {} # 在空字典里进行了conn赋值,self.dic={conn:{},}

def read(self, conn, mask): # 接收了conn和mask

try: # 加异常防止客户端突然断开

if not self.dic[conn]: # 判断self.dic[conn]里面是否是空字典,如果是空字典,代表第一次进来

print('====第一次进来')

data = conn.recv(1024) # conn接收了客户端发来的数据

print("data==",str(data, encoding='utf-8'))

cmd, filename,filesize = str(data, encoding='utf-8').split('|') # 把接收到客户端发来的包解开拿到cmd,filename,filesize个信息

self.dic = {conn: {"cmd": cmd, "filename": filename, "filesize": int(filesize)}} # 把拿到的cmd,filename,filesize信息放到self.dic字典里去后程序返回到handle()函数里的events继续监听

print(self.dic)

if cmd == 'put': # 如果接收的信息是put

conn.send(bytes("OK", encoding='utf8')) # 给客户端返回一条数据

if self.dic[conn]['cmd'] == 'get':

file = os.path.join(BASE_DIR, "upload", filename)

if os.path.exists(file):

print("文件存在的情况,返回YES给客户端")

filesize = os.path.getsize(file)

self.dic[conn]['filesize'] = filesize

print("self.dic",self.dic)

send_info = '%s|%s' % ('YES', filesize)

conn.send(bytes(send_info, encoding='utf8'))

else:

print("文件不存在情况下")

send_info = '%s|%s' % ('NO', 0)

conn.send(bytes(send_info, encoding='utf8'))

self.dic[conn] = {} #文件不存在的情况下,要将清空字典

else: # 如果不是空字典代表不是第一次进来

print('不是第一次来的')

print(self.dic)

if self.dic[conn].get('cmd', None): # 对接收的命令进行分发判断是put还是get

cmd = self.dic[conn].get('cmd')

if hasattr(self, cmd): # 如果cmd=put调用put函数,如果是cmd=get函数调用get函数

func = getattr(self, cmd)

func(conn)

else:

print("error cmd!")

conn.close()

else:

print("error cmd!")

conn.close()

except Exception as e:

print('断开的客户端信息是:', conn)

self.sel.unregister(conn) # 如果没有接收到数据做一个关闭解除

conn.close()

# put上传函数

def put(self, conn):

fileName = self.dic[conn]['filename']

fileSize = self.dic[conn]['filesize']

# print("BASE_DIR",BASE_DIR)

path = os.path.join(BASE_DIR, "upload", fileName) # 拿到要接收的信息

# print(fileName,fileSize,path)

recv_data = conn.recv(1024) # 接收客户端上传的数据1024字节

self.hasReceived += len(recv_data) # 把接收的数据累加到变量self.hasReceived

with open(path, 'ab') as f: # 打开文件

f.write(recv_data) # 把接收的数据写到文件里去

if fileSize == self.hasReceived: # 判断文件大小跟接收大小是否一样

if conn in self.dic.keys(): # 如果文件大小跟接收大小一样清空字典

self.dic[conn] = {}

self.hasReceived = 0 #S上传结束之后,需要将self.hasReceived 重置成功

print("%s 上传完毕!" % fileName)

def get(self,conn):

fileName = self.dic[conn]['filename']

file = os.path.join(BASE_DIR, "upload", fileName)

# fileSize = os.path.getsize(file)

fileSize=self.dic[conn]['filesize']

data = conn.recv(1024) # conn接收了客户端发来的数据

dataOK = str(data, encoding='utf-8')

if dataOK == 'OK':

with open(file, 'rb') as f: # 打开文件

while fileSize > self.hasSend: # 循环的发送文件给客户端

contant = f.read(1024)

recv_size = len(contant)

conn.send(contant)

self.hasSend += recv_size

s = str(int(self.hasSend / fileSize * 100)) + "%"

print("正在下载文件: " + fileName + " 已经下载:" + s)

if fileSize == self.hasSend: # 判断文件大小跟接收大小是否一样

if conn in self.dic.keys(): # 如果文件大小跟接收大小一样清空字典

self.dic[conn] = {}

print("%s 下载完毕!" % fileName)

self.hasSend = 0

if __name__ == '__main__':

selectFtpserver()

client.py

import socket

import os,sys

BASE_DIR=os.path.dirname(os.path.abspath(__file__))

class selectFtpClient:

def __init__(self):

self.args=sys.argv #sys.argv在命令行输入的参数,第一个参数默认文件名,第二个参数跟IP地址和端口

if len(self.args)>1: #如果大于1把第二个参数俩个值赋值给port

self.port=(self.args[1],int(self.args[2]))

else:

self.port=("127.0.0.1",8899) #如果没有第二个参数默认取这个

self.create_socket() #

self.command_fanout() #进行命令分发

self.mainPath = os.path.join(BASE_DIR, 'filename') # 获取该客户端下的filename路径

#create_socket函数创建socket对象连接服务端

def create_socket(self):

try:

self.sk = socket.socket()

self.sk.connect(self.port)

print('连接FTP服务器成功!')

except Exception as e:

print("eroor:",e)

#command_fanout()函数进行命令分发

def command_fanout(self):

while True:

try:

print("----------------welcome to ftp client-------------------")

self.help_info()

cmd_info = input('>>>请输入操作命令:').strip() # put 12.png images

if not cmd_info:

continue

cmd,file = cmd_info.split() ##按照空格分隔

# print("命令是什么", cmds)

if cmd == "quit":

break

if hasattr(self, cmd):

func = getattr(self, cmd)

func(cmd,file)

Tag = input("是否继续进入ftp clinet,请选择Y/N:").strip()

if Tag.upper() == 'Y':

continue

else:

break

else:

print('No such command ,please try again')

except Exception as e: # server关闭了

print('%s' % e)

break

def help_info(self):

print ('''

get + (文件名) 表示下载文件

put + (文件名) 表示上传文件

quit 表示退出登录

''')

#put()上传函数

def put(self,cmd,file):

if os.path.isfile(file): #判断本地文件是否存在

fileName = os.path.basename(file) #取出文件的名字

fileSize = os.path.getsize(file) #取出文件的大小

fileInfo = '%s|%s|%s'%(cmd,fileName,fileSize) #给文件名字大小打包成fileInf

self.sk.send(bytes(fileInfo, encoding='utf8')) #调用send方法把fileInf发给服务端

recvStatus = self.sk.recv(1024) #接收服务端返回的OK内容

print('recvStatus' , recvStatus)

hasSend = 0

if str(recvStatus, encoding='utf8') == "OK": #如果接收到服务端返回的OK

with open(file, 'rb') as f: #打开文件

while fileSize > hasSend : #循环的去上传文件

contant = f.read(1024)

recv_size = len(contant)

self.sk.send(contant)

hasSend += recv_size

s=str(int(hasSend/fileSize*100))+"%"

print("正在上传文件: "+fileName+" 已经上传:" +s)

print('%s文件上传完毕' % (fileName,))

else:

print('要上传的文件不存在')

#get()下载函数

def get(self,cmd,fileName):

path = os.path.join(BASE_DIR, "download", fileName) # 拿到要接收的信息

fileSize=0

fileInfo = '%s|%s|%s' % (cmd, fileName, fileSize) # 给文件名字大小打包成fileInf

print(fileInfo)

self.sk.send(bytes(fileInfo, encoding='utf8')) # 调用send方法把fileInfo发给服务端

recvdata = self.sk.recv(1024) # 接收服务端返回的是否存在文件内容

recvStatus, fileSize = str(recvdata, encoding='utf-8').split('|')

print("recvStatus==",recvStatus,fileSize)

fileSize = int(fileSize)

hasReceived = 0

if recvStatus == "YES": # 如果接收到服务端返回的YES

self.sk.send(bytes('OK', encoding='utf8')) # 通知服务端可以正常下载了

while fileSize > hasReceived: # 循环的发送文件给客户端

recv_data = self.sk.recv(1024) # 接收客户端上传的数据1024字节

hasReceived += len(recv_data) # 把接收的数据累加到变量self.hasReceived

print("hasReceived",hasReceived)

with open(path, 'ab') as f: # 打开文件

f.write(recv_data) # 把接收的数据写到文件里去

if fileSize == hasReceived: # 判断文件大小跟接收大小是否一样

print("%s 下载完毕!" % fileName)

recvStatus = 'YESS'

else:

print('要下载的文件不存在')

if __name__=='__main__':

selectFtpClient()

以上就是python 基于selectors库实现文件上传与下载的详细内容,更多关于python 上传下载的资料请关注脚本之家其它相关文章!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python文件传输库,python 基于selectors库实现文件上传与下载 的相关文章

随机推荐

  • 面试常问的事情与题目

    随便给份工作我吧 提示 xff1a 面试多总结一下经验 xff0c 抓重点 xff0c 而不是什么都想准备好 其实自己就是一个菜狗 xff0c 备考了半年 xff0c 什么鸡儿都忘记了 xff0c 从零开始 文章目录 前言一 基本流程大概二
  • 我的常用基础指令

    docker相关 run it ubuntu span class token function bash span i 是以交互式的方式启动 t 是以终端的形式启动 p 映射端口号 xff1a 原始端口号 指定端口号启动 例 xff1a
  • vue jqurey 等前端常用

    vue components 注册组件 如 xff1a span class token keyword import span SelectDict span class token keyword from span span clas
  • 《Linux 内核完全注释》阅读笔记

    在阅读源代码之前 xff0c 有必要对Linux内核的体系结构 源代码的目录结构有个宏观地了解 xff0c Linux内核完全注释 非常详细地介绍了这方面的内容 xff0c 所以 这里仅仅进行概述性的讨论 xff0c 以便让所有的笔记构成一
  • 关于Java-stream的一下日常使用

    惰式执行 对 stream的操作并不会立即执行 如果用户真正需要的时候才会执行 span class token class name Stream span span class token punctuation span span c
  • 怎么获取别人服务器信息失败,获取服务器信息失败

    获取服务器信息失败 内容精选 换一换 1 若希望以主席身份入会 xff0c enter code必须传入主席密码 若希望以来宾身份入会 xff0c 当会议要求来宾密码时 xff0c enter code必须传入来宾密码 xff0c 会议不要
  • 我的世界服务器合成表修改,【组件教程】行为包03:修改合成表

    大家好我是那个谁 xff0c 今天为大家带来组件系列教程的第三课 xff0c 在上一课中我们对于掉落物进行了详细的讲解 xff0c 这一课中我们要把目光看向我的世界另一重要玩法组成部分 xff1a 合成 打开原版行为包中recipes文件夹
  • liunx 全盘查找_linux查找文件命令find怎么用

    linux查找文件命令find怎么用 Linux 文件搜索命令find的操作使用方法如下 xff1a 1 全盘搜索 xff0c 也可以指定目录搜索 find 搜索目录 name 目标名字 xff0c find name file 2 这样搜
  • 程序员的成长之路:回顾初心,质疑自我

    经过3 4年的成长期 xff0c 你说日常写代码无压力 xff0c 代码质量也可以 xff0c 完成日常工作后 xff0c 就不知道做什么 xff1f 如果现在的你正好是这么一种状态 xff0c 想提升却不知道往哪走 xff1f 那你一定进
  • CentOS 7中安装Oracle JDK

    1 前往Oracle官网http www oracle com technetwork java javase downloads index html下载JDK xff0c 这里我们选择rpm包 xff08 注意 xff1a 下载前须接受
  • 给android程序添加页面,向 Android 应用中添加闪屏页和启动页

    向 Android 应用中添加闪屏页和启动页 开启 Flutter 的体验需要短暂地等待 Dart 的初始化 一个完整的 Flutter 应用还额外需要 Android 应用程序标准的初始化时间 Flutter 支持在 Android 应用
  • ArchLinux必备命令记录(manjaro)

    1 添加新账户 useradd username新建账户 useradd d home xxx m xxx创建用户 xff0c 并同时生成用户目录 xff0c 不然账户无法正常启用 passwd username修改密码 userdel f
  • js使用lottie读取json文件并修改文件参数后渲染

    js使用lottie读取json文件并修改文件参数后渲染 1 效果图 说明 xff1a 车辆模型是通过json文件渲染的 2 代码 2 1 引入lottie js xff08 如果没有 xff0c 网上资源很多 xff0c 请自行下载 xf
  • Mybatis基础+增删改查(代码示例)

    目录 Mybatis基础 43 增删改查 xff08 代码示例 xff09 首先什么是MyBatis xff1f MyBatis中文文档 xff08 学习参考资料 xff09 xff1a MyBatis 基础框架搭建源码 xff1a MyB
  • KVM虚拟化工具简介及安装

    1 KVM简介 Kernel based Virtual Machine的简称 xff0c 是一个开源的系统虚拟化模块 xff0c 自Linux2 6 20之后集成在Linux的各个主要发行版本中 它使用Linux自身的调度器进行管理 xf
  • 按键消抖

    按键消抖 按键是FPGA实验工程中常见的电子元器件 xff0c 通常用作系统复位信号或者控制 外部信号的输入 按键消抖主要针对的是机械弹性开关 xff08 按下去 xff0c 一旦松开就会弹上去 xff09 xff0c 当机械触点断开 闭合
  • java ee 值范围_JAVAEE之内置对象和属性范围

    内置对象和属性范围 四种属性范围 九个内置对象 1 内置对象 如果说想要使用一个对象 xff0c 必须new 出来 xff0c 但是在我们的jsp操作中 xff0c 发现我们使用过的out request对象没有进行实例化 xff0c 类似
  • VsCode C++使用相对路径读取文件失败的原因及解决方案

    VsCode C 43 43 使用相对路径读取文件失败的原因及解决方案 1 读取失败的原因2 解决方案 1 读取失败的原因 文件读取失败的原因之一便是文件路径错误 xff0c 这里的错误包含两个方面 xff1a 一个是路径中的某个文件夹或者
  • Ngnix https重定向后变成http问题解决

    一开始页面报错 Mixed Content span class token operator span The page at span class token string 39 xxx 39 span was loaded over
  • python文件传输库,python 基于selectors库实现文件上传与下载

    server py import selectors import socket import os import time BASE DIR 61 os path abspath os path dirname file class se