zoukankan      html  css  js  c++  java
  • 简单的实现文件上传下载功能

    简单的实现文件上传下载功能,其中用到了socketserver,可以实现多用户上传和下载文件

    服务端代码:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: Xiaobai Lei
    import socket
    import subprocess
    import os
    import json
    import hashlib
    import struct
    import socketserver
    
    class MyServer(socketserver.BaseRequestHandler):
        """文件上传下载服务端"""
        address_family = socket.AF_INET
        socket_type = socket.SOCK_STREAM    # tcp流类型
        allow_reuse_address = False
        max_packet_size = 8192
        coding = 'utf-8'
        request_queue_size = 5  # 队列最长数量
        server_upload_dir = 'file_upload'
        server_download_dir = 'file_download'
    
        def server_close(self):
            self.request.close()
    
        def close_request(self, request):
            request.close()
    
        def handle(self):
            print('from client ', self.client_address)
            while True:
                try:
                    head_struct = self.request.recv(4)
                    if not head_struct:break
    
                    head_len = struct.unpack('i', head_struct)[0]
                    head_json = self.request.recv(head_len).decode(self.coding)
                    head_dic = json.loads(head_json)
    
                    action = head_dic['action']
                    if hasattr(self, action):
                        func = getattr(self, action)
                        func(head_dic)
                except Exception:
                    break
    
        def put(self, args):
            """实现文件上传"""
            file_path = os.path.normpath(os.path.join(self.server_upload_dir, args['filename']))
            filesize = args['filesize']
            recv_size = 0  # 记录读取文件的大小
            file_md5 = hashlib.md5()    # 计算文件的md5值,保证上传的完整性
            with open(file_path, "wb") as f:
                while recv_size < filesize:
                    recv_data = self.request.recv(self.max_packet_size)
                    file_md5.update(recv_data)
                    f.write(recv_data)
                    recv_size += len(recv_data)
            file_md5_code = file_md5.hexdigest()  # 获取文件md5的值,字符串形式
            self.request.send(b"ok")
            recv_md5_code = self.request.recv(self.max_packet_size).decode(self.coding)    # 接收客户端发来的md5值
            if recv_md5_code == file_md5_code:
                print("%s文件上传成功,大小为%s字节!"%(args['filename'], filesize))
                self.request.send(b"1000")
            else:
                self.request.send(b"1001")
    
        def download(self, args):
            """实现文件下载"""
            file_path = os.path.normpath(os.path.join(self.server_download_dir, args['filename']))
            if not os.path.exists(file_path):
                print('file:%s is not exists' % file_path)
                return
            else:
                filesize = os.path.getsize(file_path)
            filesize_struct = struct.pack('i', filesize)
            # 发送服务端文件的大小
            self.request.send(filesize_struct)
            send_size = 0  # 记录读取文件的大小
            file_md5 = hashlib.md5()  # 计算文件的md5值,保证上传的完整性
            # 接下来传输文件
            with open(file_path, "rb") as f:
                for line in f:
                    file_md5.update(line)
                    self.request.send(line)
                    send_size += len(line)
            # 发送文件的md5,判断文件一致性
            file_md5_code = file_md5.hexdigest()  # 获取文件md5的值,字符串形式
            file_md5_client = self.request.recv(self.max_packet_size).decode(self.coding)
            if file_md5_client == file_md5_code:
                print("%s文件下载成功,大小为%s字节!" % (args['filename'], filesize))
                self.request.send(b"1000")
            else:
                self.request.send(b"1001")
    
    
    
    if __name__ == '__main__':
        ip_port = ('127.0.0.1', 9999)
        server = socketserver.ThreadingTCPServer(ip_port, MyServer)
        server.serve_forever()

    客户端代码:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: Xiaobai Lei
    import socket
    import subprocess
    import os
    import json
    import hashlib
    import struct
    
    
    class MyTcpClient:
        address_family = socket.AF_INET
        socket_type = socket.SOCK_STREAM
        allow_reuse_address = False
        max_packet_size = 8192
        coding = 'utf-8'
        request_queue_size = 5
        # client_download_dir = 'file_download'
    
        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:
                cmd = input(">>: ").strip()
                if not cmd:continue
                action,filename = cmd.split()
                if hasattr(self, action):
                    func = getattr(self, action)
                    func((action,filename))
    
        def put(self, args):
            """实现文件上传"""
            action, filename = args[0],args[1]
            if not os.path.isfile(filename):
                print('file:%s is not exists' % filename)
                return
            else:
                filesize = os.path.getsize(filename)
            head_dic = {'action': action, 'filename': os.path.basename(filename), 'filesize': filesize}
            head_json = json.dumps(head_dic)
            head_json_bytes = head_json.encode('utf8')
            head_struct = struct.pack("i", len(head_json_bytes))
            # 先发送字典数据的pack字节
            self.socket.send(head_struct)
            # 接着发送字典数据
            self.socket.send(head_json_bytes)
            send_size = 0
            file_md5 = hashlib.md5()
            # 最后发送需要传输的文件
            with open(filename, 'rb') as f:
                for line in f:
                    file_md5.update(line)
                    self.socket.send(line)
                    send_size += len(line)
            # 发送文件的md5,判断文件一致性
            file_md5_code = file_md5.hexdigest()    # 获取文件md5的值,字符串形式
            self.socket.recv(self.max_packet_size)
            self.socket.send(file_md5_code.encode(self.coding)) # 发送文件的md5值给服务端
            code = self.socket.recv(self.max_packet_size).decode(self.coding)
            if code == "1000":
                print("%s字节的%s文件上传成功!"%(send_size, filename))
            else:
                print("上传失败,请重新上传!")
    
        def download(self, args):
            """实现文件下载"""
            print(args)
            action, filename = args[0], args[1]
            head_dic = {'action': action, 'filename': os.path.basename(filename)}
            head_json = json.dumps(head_dic)
            head_json_bytes = head_json.encode('utf8')
            head_struct = struct.pack("i", len(head_json_bytes))
            # 先发送字典数据的pack字节
            self.socket.send(head_struct)
            # 接着发送字典数据
            self.socket.send(head_json_bytes)
            # 接收服务端要发送过来的文件大小数据
            filesize_struct = self.socket.recv(4)
            filesize = struct.unpack('i', filesize_struct)[0]
            recv_size = 0  # 记录读取文件的大小
            file_md5 = hashlib.md5()  # 计算文件的md5值,保证上传的完整性
            with open(filename, "wb") as f:
                while recv_size < filesize:
                    recv_data = self.socket.recv(self.max_packet_size)
                    file_md5.update(recv_data)
                    f.write(recv_data)
                    recv_size += len(recv_data)
            file_md5_code = file_md5.hexdigest()  # 获取文件md5的值,字符串形式
            self.socket.send(file_md5_code.encode(self.coding)) # 发送文件的md5值给服务端
            code = self.socket.recv(self.max_packet_size).decode(self.coding)
            if code == "1000":
                print("%s字节的%s文件下载成功!"%(recv_size, filename))
            else:
                print("下载失败,请重新下载!")
    
    
    if __name__ == '__main__':
        client = MyTcpClient(('127.0.0.1', 9999))
        client.run()
  • 相关阅读:
    开发工具(四)
    开发工具(三)
    调试(二)
    调试(一)
    jsp乱码解决大全(转自csdn一高手)
    开发工具(二)
    开发工具
    在 SQL Server 2000 中对链接服务器运行分布式事务在您安装 Windows Server 2003 或 Windows XP Service Pack 2 时可能收到 7391 错误信息
    蓝桥杯试题
    How to lay pipelines
  • 原文地址:https://www.cnblogs.com/leixiaobai/p/10893280.html
Copyright © 2011-2022 走看看