前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python 实战:文件下载功能

Python 实战:文件下载功能

作者头像
Devops海洋的渔夫
发布2019-06-02 13:56:39
7930
发布2019-06-02 13:56:39
举报
文章被收录于专栏:Devops专栏

实战功能需求

使用python编写客户端以及服务端读取、下载文件的功能。

客户端:请求需要下载的文件名,然后从服务端根据返回的数据,写成一个文件 服务端:根据客户端发送过来的需要下载的文件名,返回该文件的内容数据

版本1.0 - 客户端首先从网络调试器中读取返回的数据,生成文件

客户端代码如下:

代码语言:javascript
复制
[root@server01 tcp_download]# vim client.py 

#coding=utf-8

from socket import *

# 创建socket
tcp_client_socket = socket(AF_INET, SOCK_STREAM)

# 服务器的地址
dest_addr = ('192.168.1.2', 8080)  # 注意 是元组,ip是字符串,端口是数字

# 链接服务器,进行tcp三次握手
tcp_client_socket.connect(dest_addr)

# 从键盘获取数据
download_file_name = input("胖子老板:你想要上面烟呀")

# 发送数据到指定的服务端
tcp_client_socket.send(download_file_name.encode("utf-8"))

# 接收对方发送过来的数据,最大接收1024个字节, 1024 = 1K , 1024*1024 = 1M , 1024*1024*1024 = 1G
recvData = tcp_client_socket.recv(1024)
print('server:',str(recvData.decode('utf-8')))

# 将受到的数据保存到一个文件中,"wb"以字节写入文件
with open("download_" + download_file_name,"wb") as f:
    f.write(recvData)

# 关闭套接字
tcp_client_socket.close()

执行如下:

可以看到,现在已经简单实现了客户端的功能了,那么下面来实现一下服务端的功能。

版本 1.1 - 客户端向服务端发送文件名,服务端简单返回“蓝利群一包”,然后客户端将内容写入文件中

服务端的返回代码如下:

代码语言:javascript
复制
[root@server01 tcp_download]# vim server.py 

#coding=utf-8

from socket import *

# 创建套接字
tcp_server_socket = socket(AF_INET, SOCK_STREAM)

# 绑定服务端提供服务的端口号
local_addr = ('', 7788) #  ip地址和端口号,ip一般不用写,表示本机的任何一个ip

# 绑定
tcp_server_socket.bind(local_addr)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其改为被动,用来监听连接
tcp_server_socket.listen(128)

while True:
    # 如果有新的客户端来链接服务端,那么就产生一个新的套接字专门为这个客户端服务
    # client_socket用来为这个客户端服务
    # tcp_server_socket就可以省下来专门等待其他新的客户端连接while True:
    client_socket, clientAddr = tcp_server_socket.accept()


    # 接收对方发送的数据
    recv_data = client_socket.recv(1024) #  1024表示本次接收的最大字节数
    if recv_data:
        print('接收到的数据为:',recv_data.decode('utf-8'))

    # 发送一些数据到客户端
    client_socket.send("yours lanliqun !".encode('utf-8'))

    # 将接收到的数据转换为字符串打印
    recv_result = str(recv_data.decode('utf-8'))
    print("recv_result",recv_result)


    # 关闭为这个客户端服务的套接字,只要关闭,就意味着不能再为这个客户端服务了。
    # 如果客户端还需要服务,则重新建立连接
    client_socket.close()

### 最后关闭监听的socket
tcp_server_socket.close()

执行如下:

好了,写到这里。已经看到客户端已经将服务端返回的文件内容都写入文件了。 也简单实现了服务端的功能。 那么下一步就是要求服务端可以根据请求的文件名读取内容,然后返回给客户端文件内容了。

版本 2.0 - 服务端读取一个文件的内容,返回客户端

首先准备好一个准备被下载的文件:

代码语言:javascript
复制
[root@server01 tcp_download]# echo 123 > 1.txt
[root@server01 tcp_download]# ls
1.txt  client.py  download_lanliqun  server.py
[root@server01 tcp_download]# 
[root@server01 tcp_download]# cat 1.txt 
123
[root@server01 tcp_download]# 

等会有客户端请求需要下载1.txt文件,然后服务端返回1.txt的文件内容,提供客户端下载。

服务端代码如下:

代码语言:javascript
复制
[root@server01 tcp_download]# vim server.py 

#coding=utf-8

from socket import *

def send_file_2_client(client_socket,clientAddr):
    # 接收从客户端需要下载的文件名
    recv_data = client_socket.recv(1024) #  1024表示本次接收的最大字节数
    if recv_data:
        file_name = recv_data.decode('utf-8')
        print('need to download file_name= %s' % file_name)
        print('client IP:',clientAddr)

    # 根据文件名读取文件数据,并返回文件内容
    file_content = None
    # 打开文件
    try:
        f = open(file_name,"rb")
        file_content = f.read()
        f.close()
    except Exception as ret:
        print("don't have download file %s" % file_name)

    # 发送打开的文件内容到客户端
    if file_content:
       #client_socket.send("yours lanliqun !".encode('utf-8'))
       client_socket.send(file_content)

def main():
    # 创建套接字
    tcp_server_socket = socket(AF_INET, SOCK_STREAM)

    # 绑定服务端提供服务的端口号
    local_addr = ('', 7788) #  ip地址和端口号,ip一般不用写,表示本机的任何一个ip

    # 绑定
    tcp_server_socket.bind(local_addr)

    # 使用socket创建的套接字默认的属性是主动的,使用listen将其改为被动,用来监听连接
    tcp_server_socket.listen(128) # 128 可以理解服务器可以同时监听128个客户端

    while True:
        # 如果有新的客户端来链接服务端,那么就产生一个新的套接字专门为这个客户端服务
        # client_socket用来为这个客户端服务
        # tcp_server_socket就可以省下来专门等待其他新的客户端连接while True:
        client_socket, clientAddr = tcp_server_socket.accept()

        # 读取并发送文件内容到客户端        
        send_file_2_client(client_socket,clientAddr)

        # 关闭为这个客户端服务的套接字,只要关闭,就意味着不能再为这个客户端服务了。
        # 如果客户端还需要服务,则重新建立连接
        client_socket.close()

    ## 最后关闭监听的socket
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

演示执行如下:

从演示中看出,客户端存在一个bug,当服务端返回空字符串的时候,客户端照样会写入一个空内容到文件中。 那么下面改改就好,加一个判断。 客户端代码如下:

代码语言:javascript
复制
[root@server01 tcp_download]# vim client.py 

#coding=utf-8

from socket import *

# 创建socket
tcp_client_socket = socket(AF_INET, SOCK_STREAM)

# 服务器的地址
dest_addr = ('127.0.0.1', 7788)  # 注意 是元组,ip是字符串,端口是数字

# 链接服务器,进行tcp三次握手
tcp_client_socket.connect(dest_addr)

# 从键盘获取数据
download_file_name = input("胖子老板:你想要上面烟呀")

# 发送数据到指定的服务端
tcp_client_socket.send(download_file_name.encode("utf-8"))

# 接收对方发送过来的数据,最大接收1024个字节, 1024 = 1K , 1024*1024 = 1M , 1024*1024*1024 = 1G
recvData = tcp_client_socket.recv(1024)
print('server:',str(recvData.decode('utf-8')))

# 当服务端返回有数据,才写入文件中
if recvData:
   # 将受到的数据保存到一个文件中,"wb"以字节写入文件
   with open("download_" + download_file_name,"wb") as f:
       f.write(recvData)

# 关闭套接字
tcp_client_socket.close()

执行演示如下:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.12.15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实战功能需求
  • 版本1.0 - 客户端首先从网络调试器中读取返回的数据,生成文件
  • 版本 1.1 - 客户端向服务端发送文件名,服务端简单返回“蓝利群一包”,然后客户端将内容写入文件中
  • 版本 2.0 - 服务端读取一个文件的内容,返回客户端
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档