码迷,mamicode.com
首页 > 编程语言 > 详细

python传输文件

时间:2018-07-10 23:34:51      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:网络编程   eve   use   symbol   数据   serve   ...   [1]   ack   

传输文件简单版

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
>> 

  

  

python传输文件

标签:网络编程   eve   use   symbol   数据   serve   ...   [1]   ack   

原文地址:https://www.cnblogs.com/xiao-apple36/p/9286610.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!