在TCP协议下通过socket模块实现文件上传
#!/usr/bin/env python # -*- coding: utf-8 -*- # desc: tcp_server_file_upload import socket import struct import json import time IP_PORT = ('127.0.0.1', 8080) BUFFERSIZE = 1024 tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #获取socket对象,并设置通过TCP协议通信 tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)#设置连接重用 tcp_server_socket.bind(IP_PORT) #绑定IP地址和端口 tcp_server_socket.listen() #监听,可指定数量 conn, addr = tcp_server_socket.accept() #建立连接 print('client ip addr:', addr) head_struct = conn.recv(4) #接收定制报头的长度 head_json_len = struct.unpack('i', head_struct)[0] #解包,获取定制报头的长度 head_json = conn.recv(head_json_len).decode('utf-8') #根据上一步解包获得的报头长度,接收报头 head = json.loads(head_json) #将json字符串类型的报头转化为python对象 file_size = head['file_size']#获取待接收文件的大小 file_name = head['file_name']#获取接收文件的名字 print(time.strftime('%Y-%m-%d %H:%M:%S'),' 开始接收文件...') #打印开始接收文件的时间 with open(file_name, 'wb') as f: #以二进制写方式打开文件 ''' 循环写入接收的文件内容 ''' while True: if file_size >= BUFFERSIZE: #如果接收的文件内容大于设置的BUFFERSIZE,就只接收BUFFERSIZE大小的内容 content = conn.recv(BUFFERSIZE) #接收客服端发送的BUFFERSIZE大小的内容 f.write(content) #在服务端写入BUFFERSIZE大小的内容 file_size -= BUFFERSIZE #将待写入的文件大小减去已接收的BUFFERSIZE大小 ''' 主要是用于服务端和客户端在同一PC上,且写入比读取快,从而导致服务端先行关闭, 造成客户端连接中断,文件传送不完整 ''' time.sleep(0.00001) else: content = conn.recv(file_size) #接收文件剩余部分 f.write(content) break print(time.strftime('%Y-%m-%d %H:%M:%S'),' 成功接收文件...') #打印文件接收完成时间 conn.close() #关闭连接 tcp_server_socket.close() #关闭服务端socket
#!/usr/bin/env python # -*- coding: utf-8 -*- # @desc: tcp_client_file_upload import socket import struct import json import os import time IP_PORT = ('127.0.0.1', 8080) BUFFERSIZE = 1024 tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #获取socket对象 tcp_client_socket.connect(IP_PORT) #连接服务端 ''' 定制化报头 ''' head = {'file_path':r'文件路径', 'file_name':r'文件名', 'file_size':0 } file_path = os.path.join(head['file_path'], head['file_name']) #获取要上传文件的完整路径 file_size = os.path.getsize(file_path) #获取文件大小 head['file_size'] = file_size #将获取到的真实文件大小设置到报头 head_json = json.dumps(head) #将报头python对象转化为json字符串 head_bytes = bytes(head_json, encoding='utf-8') #将报头json字符串转化为bytes字节码 head_struct = struct.pack('i', len(head_bytes)) #将报头bytes字节码以'integer'类型打包为4个字节 tcp_client_socket.send(head_struct) #发送打包为4个字节的报头 tcp_client_socket.send(head_bytes) #发送定制化报头 print(time.strftime('%Y-%m-%d %H:%M:%S'),' 开始发送文件...') #打印开始发送文件的时间 with open(file_path, 'rb') as f: #以二进制读的方式打开文件 ''' 循环读取文件内容并发送给服务端 ''' while True: if file_size >= BUFFERSIZE: #如果发送文件的大小大于BUFFERSIZE,只读取BUFFERSIZE大小的内容 content = f.read(BUFFERSIZE) #读取BUFFERSIZE大小的内容 tcp_client_socket.sendall(content) #发送读取的文件内容 file_size -= BUFFERSIZE #文件大小减去已发送文件的大小 else: content = f.read(file_size) #读取剩余文件内容 tcp_client_socket.sendall(content) #发送文件读取的文件内容 break #终止循环 print(time.strftime('%Y-%m-%d %H:%M:%S'),' 文件发送成功...') #大于文件发送完成的时间 tcp_client_socket.close() #关闭socket