python傳輸文件


傳輸文件簡單版

server端:

import socket
import struct
import json
import os

share_dir = r'C:\py3Project\路飛\第三模塊\第二章網絡編程\05_文件傳輸\簡單版本\server\share'
IP_PORT = ('127.0.0.1', 8999)

def bytes2human(n):
    symbols = ('K', 'M', 'G', 'T', 'P', 'E')
    prefix = {}
    for i, s in enumerate(symbols):
        # << 左移” 左移一位表示乘2 即1 << 1=2,二位就表示4 即1 << 2=4,
        # 10位就表示1024 即1 << 10=1024 就是2的n次方
        prefix[s] = 1 << (i + 1) * 10
    for s in reversed(symbols):
        if n >= prefix[s]:
            value = float(n) / prefix[s]
            return '%.2f%s' % (value, s)
    return "%sB" % n

def get(conn,file_name):
    # 3、以讀的方式打開文件,讀取文件內容發送給客戶端
    # 第一步:制作固定長度的報頭
    print('get')
    try:
        header_dict = {
            'file_name': file_name,
            'md5': 'xxx',
            'file_size': os.path.getsize(os.path.join(share_dir, file_name))

        }

        header_json = json.dumps(header_dict, ensure_ascii='False', indent=2)
        header_bytes = header_json.encode('utf-8')
        # 第二步:先發送報頭的長度
        conn.send(struct.pack('i', len(header_bytes)))

        # 第三步:再發報頭
        conn.send(header_bytes)

        # 第四步:再發送真實的數據
        with open(os.path.join(share_dir, file_name), 'rb') as f:
            for line in f:
                conn.send(line)

    except Exception as e:
        print(e)


def put(conn, file_name):
    """
     接收客戶端上傳文件
    :param conn:
    :param file_name:
    :return:
    """
    # 2、以寫的方式打開一個新文件,接收客戶端發來的文件的內容寫入服務端新文件
    # 第一步:先收報頭的長度
    header_len = conn.recv(4)
    header_size = struct.unpack('i', header_len)[0]

    # 第二步:再收報頭
    header_json = conn.recv(header_size).decode('utf-8')

    # 第三步:從報頭中解析出對真實數據的描述信息
    header_dict = json.loads(header_json)
    file_size = header_dict['file_size']
    file_name = header_dict['file_name']

    print(os.path.join(share_dir, file_name))
    # 第四步:接收真實的數據,寫入文件
    with open(os.path.join(share_dir, file_name), 'wb') as f:
        recv_size = 0
        while recv_size < file_size:
            line = conn.recv(1024)
            f.write(line)
            recv_size += len(line)
            print('總大小:%s   已上傳大小:%s' % (bytes2human(file_size), bytes2human(recv_size)))


def run():
    server = socket.socket(socket.AF_INET,  socket.SOCK_STREAM)
    server.bind(IP_PORT)

    server.listen(5)
    print('starting...')

    while True:

        conn, addr = server.accept()
        print(addr)

        while True:
            try:
                # 1 收命令
                res = conn.recv(1024)  # b' get a.txt'
                if not res:break
                # 2、解析命令,提取相應命令參數
                cmds = res.decode('utf-8').split()  # [get, a.txt]
                if cmds[0] == 'get':
                    get(conn, cmds[1])  # 下載文件
                    # file_name = cmds[1]
                elif cmds[0] == 'put':
                    put(conn, cmds[1])  # 上傳文件
            except ConnectionResetError: #適用於windows操作系統
                break
        conn.close()

    server.close()


if __name__ == '__main__':
    run()

  

 

client端

  

#!/usr/bin/env python3 
# -*- coding: utf-8 -*-


import socket
import struct
import json
import os

share_dir = r'C:\py3Project\路飛\第三模塊\第二章網絡編程\05_文件傳輸\簡單版本\client\download'
IP_PORT = ('127.0.0.1', 8999)


def bytes2human(n):
    symbols = ('K', 'M', 'G', 'T', 'P', 'E')
    prefix = {}
    for i, s in enumerate(symbols):
        # << 左移” 左移一位表示乘2 即1 << 1=2,二位就表示4 即1 << 2=4,
        # 10位就表示1024 即1 << 10=1024 就是2的n次方
        prefix[s] = 1 << (i + 1) * 10
    for s in reversed(symbols):
        if n >= prefix[s]:
            value = float(n) / prefix[s]
            return '%.2f%s' % (value, s)
    return "%sB" % n


def get(client, file_name):
    # 2、以寫的方式打開一個新文件,接收服務端發來的文件的內容寫入客戶的新文件
    # 第一步:先收報頭的長度
    header_len = client.recv(4)
    header_size = struct.unpack('i', header_len)[0]

    # 第二步:再收報頭
    header_json = client.recv(header_size).decode('utf-8')

    # 第三步:從報頭中解析出對真實數據的描述信息
    header_dict = json.loads(header_json)
    file_size = header_dict['file_size']
    file_name = header_dict['file_name']

    print(os.path.join(share_dir, file_name))
    # 第四步:接收真實的數據,寫入文件
    with open(os.path.join(share_dir, file_name), 'wb') as f:
        recv_size = 0
        while recv_size < file_size:
            line = client.recv(1024)
            f.write(line)
            recv_size += len(line)
            print('總大小:%s   已下載大小:%s' % (bytes2human(file_size), bytes2human(recv_size)))


def put(client, file_name):
    # 向服務端上傳文件
    print('put')
    try:
        if not os.path.isfile(os.path.join(share_dir, file_name)):
            print('file:%s is not exists' % os.path.join(share_dir, file_name))
            return
        else:
            file_size = os.path.getsize(os.path.join(share_dir, file_name))
            header_dict = {
                'file_name': file_name,
                'md5': 'xxx',
                'file_size': file_size

            }

            header_json = json.dumps(header_dict, ensure_ascii='False', indent=2)
            header_bytes = header_json.encode('utf-8')
            # 第二步:先發送報頭的長度
            client.send(struct.pack('i', len(header_bytes)))

            # 第三步:再發報頭
            client.send(header_bytes)

            # 第四步:再發送真實的數據
            with open(os.path.join(share_dir, file_name), 'rb') as f:
                for line in f:
                    client.send(line)

    except Exception as e:
        print(e)


def run():
    client = socket.socket(socket.AF_INET,  socket.SOCK_STREAM)
    client.connect(IP_PORT)

    while True:
        # 1、發命令
        cmd = input('>> ').strip()  # 'get a.txt'
        if not cmd:continue
        client.send(cmd.encode('utf-8'))

        if cmd.startswith('get'):
            get(client, cmd.split()[1])
        elif cmd.startswith('put'):
            put(client, cmd.split()[1])

    client.close()


if __name__ == '__main__':
    run()

 

輸出結果

sever:
starting...
('127.0.0.1', 19074)
get
get
C:\Users\jingjing\PycharmProjects\py3Project\路飛\第三模塊\第二章網絡編程\05_文件傳輸\簡單版本\server\share\3.jpeg
總大小:75.36K   已上傳大小:1.00K
總大小:75.36K   已上傳大小:2.00K
……
總大小:75.36K   已上傳大小:75.36K


client:


>> get 1.pptx
C:\py3Project\路飛\第三模塊\第二章網絡編程\05_文件傳輸\簡單版本\client\download\1.pptx
總大小:970.93K   已下載大小:1.00K
總大小:970.93K   已下載大小:2.00K
……
總大小:970.93K   已下載大小:970.93K
>> put 3.jpeg
put
>> 

  

傳輸文件優化版

server端:

import socket
import struct
import json
import os


class TCPServer:

    IP_PORT = ('127.0.0.1', 8999)
    request_queue_size = 5
    allow_reuse_address = False
    max_packet_size = 8192

    share_dir = r'C:\py3Project\路飛\第三模塊\第二章網絡編程\05_文件傳輸\簡單版本\server\share'

    def __init__(self, address=IP_PORT, bind_and_activate=True):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if bind_and_activate:
            try:
                self.server.bind(address)
                self.server.listen(self.request_queue_size)
                print('starting...')

            except Exception as e:
                self.server.close()
                raise e

    def get_request(self):
        """Get the request and client address from the socket.
        """
        return self.server.accept()

    def run(self):
        while True:
            self.conn, self.client_addr = self.get_request()
            print('from client ', self.client_addr)
            while True:
                try:
                    # 1 收命令
                    res = self.conn.recv(self.max_packet_size)  # b' get a.txt'
                    if not res: break
                    # 2、解析命令,提取相應命令參數
                    cmds = res.decode('utf-8').split()  # [get, a.txt]
                    if hasattr(self, cmds[0]):
                        func = getattr(self, cmds[0])
                        func(cmds[1])
                except ConnectionResetError:  # 適用於windows操作系統
                    break
            self.conn.close()

        self.server.close()

    def put(self, file_name):
        """
         接收客戶端上傳文件
        :param conn:
        :param file_name:
        :return:
        """
        print('get file %s' % file_name)

        # 2、以寫的方式打開一個新文件,接收客戶端發來的文件的內容寫入服務端新文件
        # 第一步:先收報頭的長度
        header_len = self.conn.recv(4)
        header_size = struct.unpack('i', header_len)[0]

        # 第二步:再收報頭
        header_json = self.conn.recv(header_size).decode('utf-8')

        # 第三步:從報頭中解析出對真實數據的描述信息
        header_dict = json.loads(header_json)
        file_size = header_dict['file_size']
        file_name = header_dict['file_name']

        print(os.path.join(self.share_dir, file_name))
        # 第四步:接收真實的數據,寫入文件
        with open(os.path.join(self.share_dir, file_name), 'wb') as f:
            recv_size = 0
            while recv_size < file_size:
                line = self.conn.recv(self.max_packet_size)
                f.write(line)
                recv_size += len(line)
                rate = recv_size / file_size * 100
                print('總大小:%s   已上傳:%%%.2f' % (self.bytes2human(file_size), rate))

    @staticmethod
    def bytes2human(n):
        symbols = ('K', 'M', 'G', 'T', 'P', 'E')
        prefix = {}
        for i, s in enumerate(symbols):
            # << 左移” 左移一位表示乘2 即1 << 1=2,二位就表示4 即1 << 2=4,
            # 10位就表示1024 即1 << 10=1024 就是2的n次方
            prefix[s] = 1 << (i + 1) * 10
        for s in reversed(symbols):
            if n >= prefix[s]:
                value = float(n) / prefix[s]
                return '%.2f%s' % (value, s)
        return "%sB" % n

    def get(self, file_name):
        # 3、以讀的方式打開文件,讀取文件內容發送給客戶端
        # 第一步:制作固定長度的報頭
        print('send file %s' % file_name)
        try:
            header_dict = {
                'file_name': file_name,
                'md5': 'xxx',
                'file_size': os.path.getsize(os.path.join(self.share_dir, file_name))

            }

            header_json = json.dumps(header_dict, ensure_ascii='False', indent=2)
            header_bytes = header_json.encode('utf-8')
            # 第二步:先發送報頭的長度
            self.conn.send(struct.pack('i', len(header_bytes)))

            # 第三步:再發報頭
            self.conn.send(header_bytes)

            # 第四步:再發送真實的數據
            with open(os.path.join(self.share_dir, file_name), 'rb') as f:
                for line in f:
                    self.conn.send(line)

        except Exception as e:
            print(e)


if __name__ == '__main__':
    s = TCPServer()
    s.run()

  

client端:

import socket
import struct
import json
import os


class TCPClient:

    IP_PORT = ('127.0.0.1', 8999)
    request_queue_size = 5
    allow_reuse_address = False
    max_packet_size = 8192
    share_dir = r'C:\py3Project\路飛\第三模塊\第二章網絡編程\05_文件傳輸\簡單版本\client\download'

    def __init__(self, address=IP_PORT, connect=True):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if connect:
            try:
                self.client.connect(address)
            except Exception as e:
                self.client.close()
                raise e

    def run(self):
        while True:
            # 1、發命令
            inp = input('>> ').strip()  # 'get a.txt'
            if not inp: continue
            self.client.send(inp.encode('utf-8'))
            cmd = inp.split()
            
            if hasattr(self, cmd[0]):
                func = getattr(self, cmd[0])
                func(cmd[1])

        client.close()

    @staticmethod
    def bytes2human(n):
        symbols = ('K', 'M', 'G', 'T', 'P', 'E')
        prefix = {}
        for i, s in enumerate(symbols):
            # << 左移” 左移一位表示乘2 即1 << 1=2,二位就表示4 即1 << 2=4,
            # 10位就表示1024 即1 << 10=1024 就是2的n次方
            prefix[s] = 1 << (i + 1) * 10
        for s in reversed(symbols):
            if n >= prefix[s]:
                value = float(n) / prefix[s]
                return '%.2f%s' % (value, s)
        return "%sB" % n

    def get(self, file_name):
        # 2、以寫的方式打開一個新文件,接收服務端發來的文件的內容寫入客戶的新文件
        # 第一步:先收報頭的長度
        header_len = self.client.recv(4)
        header_size = struct.unpack('i', header_len)[0]

        # 第二步:再收報頭
        header_json = self.client.recv(header_size).decode('utf-8')

        # 第三步:從報頭中解析出對真實數據的描述信息
        header_dict = json.loads(header_json)
        file_size = header_dict['file_size']
        file_name = header_dict['file_name']

        print(os.path.join(self.share_dir, file_name))
        # 第四步:接收真實的數據,寫入文件
        with open(os.path.join(self.share_dir, file_name), 'wb') as f:
            recv_size = 0
            while recv_size < file_size:
                line = self.client.recv(self.max_packet_size)
                f.write(line)
                recv_size += len(line)
                rate = recv_size / file_size * 100
                print('總大小:%s   已下載:%%%.2f' % (self.bytes2human(file_size),rate))

    def put(self, file_name):
        # 向服務端上傳文件
        print('put')
        try:
            if not os.path.isfile(os.path.join(self.share_dir, file_name)):
                print('file:%s is not exists' % os.path.join(self.share_dir, file_name))
                return
            else:
                file_size = os.path.getsize(os.path.join(self.share_dir, file_name))
                header_dict = {
                    'file_name': file_name,
                    'md5': 'xxx',
                    'file_size': file_size
    
                }
    
                header_json = json.dumps(header_dict, ensure_ascii='False', indent=2)
                header_bytes = header_json.encode('utf-8')
                # 第二步:先發送報頭的長度
                self.client.send(struct.pack('i', len(header_bytes)))
    
                # 第三步:再發報頭
                self.client.send(header_bytes)
    
                # 第四步:再發送真實的數據
                with open(os.path.join(self.share_dir, file_name), 'rb') as f:
                    for line in f:
                        self.client.send(line)
    
        except Exception as e:
            print(e)


if __name__ == '__main__':
    c = TCPClient()
    c.run()

  

輸出結果:

 

sever:
starting...
from client  ('127.0.0.1', 3500)
send file 3.jpeg
get file 1.pptx
C:\py3Project\路飛\第三模塊\第二章網絡編程\05_文件傳輸\簡單版本\server\share\1.pptx
總大小:970.93K   已上傳:%0.82
……
總大小:970.93K   已上傳:%99.96
總大小:970.93K   已上傳:%100.00


client:
 C:/py3Project/路飛/第三模塊/第二章網絡編程/05_文件傳輸/簡單版本/client/file_client.py
>> get 3.jpeg
C:\py3Project\路飛\第三模塊\第二章網絡編程\05_文件傳輸\簡單版本\client\download\3.jpeg
總大小:75.36K   已下載:%10.62
……
總大小:75.36K   已下載:%99.49
總大小:75.36K   已下載:%100.00
>> put 1.pptx
put
>> 

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM