python 之selectors 实现文件上传下载
1.文件目录
selector_FTP ——————
clientfile —————— 存放用户文件路径
selector_client.py——
selector_server.py——
serverfile —————— 存放服务器文件路径
注:实现的简约版的FTP,不支持断点续传、断点下载等操作
且只支持普通上传下载 用selector实现,支持多条客户端链接同时下载、上传 ,切勿多个客户端同时上传、下载同一个文件。
服务端
selector_server.py
def get(conn,cmd): 下载文件
def put(conn,cmd): 上传文件
def accept(sock, mask): selector 注册方法
def read(conn, mask): selector 注册方法
selector_server.py
def get(conn,cmd): 下载文件
def put(conn,cmd): 上传文件
def progress(recive_size,file_size,tips) 显示下载进度方法
例子:
clientfile 里面有一个3D.pdf 在客户端输入命令 put 3D.pdf 后 serverfile 文件夹下会有3D.pdf
serverfile 里面有一个test.zip 在客户端输入命令 get test.zip 后 clientfile 文件夹下会有test.zip
服务器端:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wenjinLi
import selectors
import socket
import os,sys
import time
import errno
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sel = selectors.DefaultSelector()def get(conn,cmd):if len(cmd.split()) > 1:filename = cmd.split()[1]file_path = '%s/serverfile/%s' % (BASE_DIR, filename) #文件路径print(file_path)if os.path.isfile(file_path): #判断文件是否存在client_file_size = 0file_size = os.stat(file_path).st_size #获得文件大小conn.send(str(file_size).encode()) #将文件大小传给客户端time.sleep(0.3)while True:with open(file_path, 'rb') as f:try:for line in f:client_file_size += len(line) #记录已经传送的文件大小conn.sendall(line)print(client_file_size, file_size)except IOError as e:if e.errno != errno.EAGAIN: # errno.EAGAIN 缓冲区满 等待下raiseelse:time.sleep(0.1) #等待0.1s进行下一次读取if client_file_size >= int(file_size): #文件传送完毕print('break')breakelse:conn.sendall('405'.encode()) # 文件不存在else:conn.sendall('401'.encode()) # 命令不存在,无法操作
def put(conn,cmd):filename = cmd.split()[1]filename = "%s/serverfile/%s" % (BASE_DIR, filename) #文件路径with open(filename, 'ab') as f:data = conn.recv(1024).decode()total_size = int(data)if total_size == '405' or total_size == '401': #文件不存在 或命令有误return Nonecurrent_size = 0while current_size <= total_size:try:recivesize = total_size - current_sizeif recivesize > 1024:recivesize = 1024data = conn.recv(recivesize)if not data: #客户端断开print('closing', conn)sel.unregister(conn)conn.close()breakcurrent_size += len(data)f.write(data)except IOError as e:if e.errno != errno.EAGAIN:raiseelse:time.sleep(0.1)print('接收完毕')def accept(sock, mask):conn, addr = sock.accept() # Should be readyconn.setblocking(False)sel.register(conn, selectors.EVENT_READ, read)def read(conn, mask):data = conn.recv(1000) # Should be readyif data:print(data)command_str = data.decode()print(command_str)if command_str.split()[0] == 'put':put(conn, command_str)elif command_str.split()[0] == 'get':get(conn,command_str)else:conn.send(b'404') # Hope it won't blockelse:print('closing', conn)sel.unregister(conn)conn.close()sock = socket.socket()
sock.bind(('localhost', 1112))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)while True:events = sel.select()for key, mask in events:callback = key.datacallback(key.fileobj, mask)
用户端:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wenjinLi
import socket
import time
import os,sys
import errno
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
def get(s,command):'''下载'''if len(command.split()) == 2:s.send(command.encode()) #通知服务器 要上传文件了else:print('下载命令有误')filename = command.split()[1]filename = "%s/clientfile/%s" % (BASE_DIR, filename) #本地地址with open(filename, 'ab') as f:data = s.recv(1024)print(data)data = data.decode()total_size = int(data)if total_size == '405':print('文件不存在')return Nonecurrent_size = 0while current_size <= total_size:try:recivesize = total_size - current_sizeif recivesize > 1024:recivesize = 1024data = s.recv(recivesize)if not data:breakcurrent_size += len(data)progress(current_size, total_size, '下载中...') #打印进度print(current_size, total_size)f.write(data)except IOError as e:if e.errno != errno.EAGAIN:raiseelse:time.sleep(0.1) #若 系统缓存已满则等带0.1秒后开始print('接收完毕')
def put(s,command):'''上传'''if len(command.split()) == 2:s.send(command.encode()) #告诉服务器要上传文件else:print('上传命令有误')if len(command.split()) > 1:filename = command.split()[1]file_path = '%s/clientfile/%s' % (BASE_DIR, filename)print(file_path)if os.path.isfile(file_path):current_file_size = 0file_size = os.stat(file_path).st_sizes.send(str(file_size).encode())time.sleep(0.3)with open(file_path, 'rb') as f:try:for line in f:s.sendall(line)current_file_size += len(line)progress(current_file_size, file_size, '上传中...')print(current_file_size,file_size)except IOError as e:if e.errno != errno.EAGAIN: # errno.EAGAIN 缓冲区满 等待下raiseelse:time.sleep(0.1) # 等待0.1s进行下一次读取else:s.send('405'.encode())print('文件不存在')else:s.send('401'.encode())print('命令不存在')def progress(recive_size,file_size,tips):'''***代表加载 _____表示还未加载部分'''lensize = 100percent = float(recive_size) / float(file_size)recivenumber = '*' * int(percent * lensize) # 已经加载的所占格数leftnumber = '_' * (lensize - int(percent * lensize)) # 未加载的所占格数sys.stdout.write('%s:%d%% [%s]\n' % (tips, percent * lensize, recivenumber + leftnumber))sys.stdout.flush()if __name__ == '__main__':HOST = 'localhost'PORT = 1112s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect((HOST,PORT))while True:msg = input('>>>请输入操作命令:').strip()if len(msg) == 0:continuecommand = msg.split()[0]if command == 'get':'''下载'''get(s,msg)elif command == 'put':'''上传'''put(s, msg)elif command == 'exit':print('成功退出')breakelse:continues.close()
转载于:https://www.cnblogs.com/nanfengxiaojin/p/6942243.html
python 之selectors 实现文件上传下载相关推荐
- Python + Paramiko实现sftp文件上传下载
最近在测试服务器那块,看了下Paramiko模块,一直都是用FileZilla工具,想了想,持续集成,更新代码可以用Parmmiko完成,还是不错的 Paramiko是用python语言写的一个模块, ...
- python实现文件上传下载
Python实现文件上传下载 环境准备: 1. 实验分两个文件,服务端(linux)和客户端(windows). 服务端运行环境:python2.x 客户端运行环境:python3.x 2. 使用了库 ...
- Django实战之文件上传下载
项目介绍 最近学习django,通过文件上传下载这个小项目,总结下常用的知识点. 做这个案例我有以下需求: 1.要支持一次上传多个文件 2.支持上传后记录上传的数据以及列表展示 3.支持下载和删除文件 ...
- linux 安装上传文件,linux常用命令(二)文件上传下载及软件安装
1.上传下载工具安装 (1)WINDOWS 到linux的文件上传及下载: windows下打开secureCRT,通过SSH连到⾄至远程linux主机: 上传下载工具安装命令:yum -y inst ...
- FTP编程实验——实现文件上传下载(基于Python3.7和PyQt5)
目录 FTP编程实现文件上传下载(基于Python3.7和PyQt5) 一.实验目的 二.实验内容 三.实验步骤 (一)服务器端 (二)客户端 [1] 界面设计 [2] 生成布局代码 [3] 功能实现 ...
- 登峰造极的python requests完成接口文件上传的案例
这篇文章主要介绍了python requests完成接口文件上传的案例,具有很好的参考价值,希望对大家有所帮助.一起跟随北凡过来看看吧 最近在准备一个公开课,主题就是利用不同的语言和不同的工具去实现文 ...
- 教你如何实现c#文件上传下载功能
简单介绍一下c#文件上传下载功能实现. NuGet 安装SqlSugar Model文件下新建 DbContext 类 public class DbContext {public DbContext ...
- [C# 网络编程系列]专题十一:实现一个基于FTP协议的程序——文件上传下载器...
引言: 在这个专题将为大家揭开下FTP这个协议的面纱,其实学习知识和生活中的例子都是很相通的,就拿这个专题来说,要了解FTP协议然后根据FTP协议实现一个文件下载器,就和和追MM是差不多的过程的,相信 ...
- SpringMVC整合fastdfs-client-java实现web文件上传下载
为什么80%的码农都做不了架构师?>>> 版权声明:本文为博主原创文章,转载请标明出处(http://blog.csdn.net/wlwlwlwl015)Thanks. 目录( ...
- JavaWeb实现文件上传下载功能实例解析
转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...
最新文章
- Qt 自定义信号与槽
- 【leetcode238】Product of Array Except Self
- 长期使用中型Access数据库的一点经验
- O太多,具体都代表什么呢?
- sql server 调用webservice
- 手把手教您如何识别翻新机子
- 通俗地讲清楚fit_transform()和transform()的区别
- 理解图像的傅里叶变换
- 同样是卖票,为啥阿里卖电影票就不卡?技术上做了啥???
- 无重复字符串的最长子串
- python的属性访问,python:如何访问函数的属性
- 在命令行中使用vs编译器
- html5小游戏抓包,wireshark抓包分析
- 前端安全——XSS攻击与防御原理详解
- linux安装smmo压缩包软件,Linux centos 安装rarlinux压缩软件 使有rarlinux
- ①变量、常量、数据类型解释 ②标识符命原则 ③sizeof使用原则 ④float型科学计数法 ⑤字符转换到ASCII表 ⑥\t 的使用意义【黑马程序员视频】
- android 获取本地图片路径
- Pdf 插入图片 | 指定位置插入图片 不改变原格式 直接操作 pdf
- android lint 安全检测,Android Lint检查
- Docker环境undertow线程数不足问题探究