python实现文件上传下载速度快_socket实现文件上传与下载(Python)

一、客户端从服务端下载文件(面向过程--函数版本)

server. py

import socket

import json

import struct

import os

# 定义路径全局变量,这里为服务端提供文件的路径

share_dir = r'/Users/xiexinran/Desktop/乱七八糟的.py/socket/server/Share'

# 建立

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# 绑定

phone.bind(('127.0.0.1', 8081))

# 监听

phone.listen(5)

# 通信循环

while True:

# 接收客户端连接请求

conn, client_addr = phone.accept()

while True:

# 接收客户端数据/命令

res = conn.recv(1024)

if not res:

continue

# 解析命令 'get 1.mp4'

cmds = res.decode('utf-8').split() # ['get','1.mp4']

filename = cmds[1] # '1.mp4'

# 以读的方式打开文件,提取文件内容发送给客户端

# 1.制作固定长度的报头

header_dic = {

'filename': filename,

'file_size': os.path.getsize('{}/{}'.format(share_dir, filename))

}

# 序列化报头

header_json = json.dumps(header_dic) # 序列化为byte字节流类型

header_bytes = header_json.encode('utf-8') # 编码为utf-8(Mac系统)

# 2.先发送报头的长度

# 2.1 将byte类型的长度打包成4位int

conn.send(struct.pack('i', len(header_bytes)))

# 2.2 再发报头

conn.send(header_bytes)

# 2.3 再发真实数据

with open('{}/{}'.format(share_dir, filename), 'rb') as f:

for line in f:

conn.send(line)

# 结束连接

conn.close()

# 关闭套接字

phone.close()

client. py

import socket

import struct

import json

# 定义路径全局变量,这里为客户端下载文件到本地的保存路径

Download_dir = r'/Users/xiexinran/Desktop/乱七八糟的.py/socket/client/Download'

# 建立

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接

phone.connect(('127.0.0.1', 8081))

while True:

cmd = input('>>> ').strip()

if not cmd:

continue

if cmd == 'quit':

break

# 给服务端发送命令

phone.send(cmd.encode('utf-8'))

# 接收服务端数据

# 1.先收报头长度

obj = phone.recv(4)

header_size = struct.unpack('i', obj)[0]

# 2.收报头

'''

header_dic = {

'filename': filename,

'file_size': os.path.getsize(filename)

}

'''

header_bytes = phone.recv(header_size)

# 3.从报头中解析出数据的真实信息(报头字典)

header_json = header_bytes.decode('utf-8')

header_dic = json.loads(header_json)

# 4.解析命令

total_size = header_dic['file_size']

filename = header_dic['filename']

# 4.接受真实数据

with open('%s/%s' % (Download_dir, filename), 'wb') as f:

recv_size = 0

while recv_size < total_size:

line = phone.recv(1024)

f.write(line)

recv_size += len(line)

# print('总大小:%s 已下载:%s' % (total_size, recv_size))

# 关闭套接字

phone.close()

客户端运行代码:

下载成功后的效果:

二、客户端向服务端下载文件(面向对象版本)

server. py

import socket

import struct

import json

import os

class MYTCPServer:

# AF_INET IPv4因特网协议

address_family = socket.AF_INET

# SOCK_STREAM 提供顺序的,可靠的双向的基于连接的字节流。可能支持带外数据传输机制。

socket_type = socket.SOCK_STREAM

# 一次性允许传输的最大字节数

max_packet_size = 8192

# 编码方式

coding = 'utf-8'

# 最大连接数

request_queue_size = 5

# 服务端文件url,这里填写自己本地服务器提供的上传文件夹

server_dir = '/Users/xiexinran/Desktop/乱七八糟的.py/socket/server2/file_upload'

def __init__(self, server_address, bind_and_activate=True):

self.server_address = server_address

self.socket = socket.socket(self.address_family,

self.socket_type)

if bind_and_activate:

try:

self.server_bind()

self.server_activate()

except:

self.server_close()

raise # 中断程序

def server_bind(self):

"""

由构造函数调用以绑定套接字

"""

self.socket.bind(self.server_address)

self.server_address = self.socket.getsockname()

def server_activate(self):

"""

由构造函数调用监听

"""

self.socket.listen(self.request_queue_size)

def server_close(self):

"""

由构造函数调用关闭服务器套接字

"""

self.socket.close()

def get_request(self):

"""

接收客户端请求

"""

return self.socket.accept()

def close_request(self, request):

"""

关闭单个客户端请求

"""

request.close()

def run(self):

while True:

self.conn, self.client_addr = self.get_request()

print('from client ', self.client_addr)

while True:

try:

head_struct = self.conn.recv(4) # 收客户端的报头长度

if not head_struct:

break

head_len = struct.unpack('i', head_struct)[0]

head_json = self.conn.recv(head_len).decode(self.coding) # 收客户端的序列化报头

head_dic = json.loads(head_json) # 反序列化报头

print(head_dic)

# head_dic = {'cmd':'put','filename':'a.txt','filesize':123123}

cmd = head_dic['cmd']

if hasattr(self, cmd):

func = getattr(self, cmd)

func(head_dic)

except Exception:

break

def put(self, args):

# 规范path字符串形式,把目录和文件名合成一个路径

file_path = os.path.normpath(os.path.join(

self.server_dir,

args['filename']

))

filesize = args['filesize']

recv_size = 0

print('----->', file_path)

with open(file_path, 'wb') as f:

while recv_size < filesize:

recv_data = self.conn.recv(self.max_packet_size)

f.write(recv_data)

recv_size += len(recv_data)

# print('recvsize:%s filesize:%s' % (recv_size, filesize))

tcpserver1 = MYTCPServer(('127.0.0.1', 8080))

tcpserver1.run()

client. py

import socket

import struct

import json

import os

class MYTCPClient:

address_family = socket.AF_INET

socket_type = socket.SOCK_STREAM

max_packet_size = 8192

coding = 'utf-8'

request_queue_size = 5

def __init__(self, server_address, connect=True):

self.server_address = server_address

self.socket = socket.socket(self.address_family,

self.socket_type)

if connect:

try:

self.client_connect()

except:

self.client_close()

raise

def client_connect(self):

self.socket.connect(self.server_address)

def client_close(self):

self.socket.close()

def run(self):

while True:

inp = input(">>: ").strip()

if not inp:

continue

l = inp.split()

cmd = l[0]

if hasattr(self, cmd):

func = getattr(self, cmd)

func(l)

def put(self, args):

cmd = args[0]

filename = args[1]

if not os.path.isfile(filename): # 判断路径是否为文件

print('file:%s is not exists' % filename)

return

else:

filesize = os.path.getsize(filename)

head_dic = {'cmd': cmd, 'filename': os.path.basename(filename), 'filesize': filesize} # 返回文件名

# print(head_dic)

head_json = json.dumps(head_dic)

head_json_bytes = bytes(head_json, encoding=self.coding)

head_struct = struct.pack('i', len(head_json_bytes))

self.socket.send(head_struct)

self.socket.send(head_json_bytes)

send_size = 0

with open(filename, 'rb') as f:

for line in f:

self.socket.send(line)

send_size += len(line)

# print(send_size)

else:

print('upload successful')

client = MYTCPClient(('127.0.0.1', 8080))

client.run()

server. py 运行结果

client. py 运行结果

上传成功后的效果图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值