Python攻克之路-网络编程(文件上传实现思路)

需求:一个server,一个client,实现client把某个文件传到server中某个目录中
分析:实际是实现数据传输,设定一个命令和一个参数(上传的内容),连接后,让用户输入命令和要传送的内容,如post 2.png,先解析这个命令,找到2.png发送到server端,命令格式自定义
1. server,client基本连接框架

[root@node2 file_upload]# cat post_server.py 
#!/usr/local/python3/bin/python3
import socket
import subprocess
sk = socket.socket()
address=('127.0.0.1',8888)
sk.bind(address)
sk.listen(3)
print('waiting...')

while True:
    conn, addr = sk.accept()
    while True:
sk.close()

inp需要有用户输入

[root@node2 file_upload]# cat post_client.py 
#!/usr/local/python3/bin/python3
import socket
import os
sk=socket.socket()
address=('127.0.0.1',8888)
sk.connect(address)

while True:
    inp=input('>>> ')  # post | path
   
sk.close()

  

2.建立连接后,post_client.py先发起动作,制定上传命令的格式post|2.png,通过|来分隔查找
a.需要一个base_dir,因为并不知道路径在那里,只知道在当前路径下,client.py的上一层就file_upload目录,再加2.png就可以,使用BASE_DIR与2.png这个内容(相对路径)进行拼接就可以了

BASE_DIR=os.path.dirname(os.path.abspath(__file__)) 

b.解析命令

cmd,path=inp.split('|') 

c.拼接路径,使用join都可以使用相关平台的默认方式拼接(linux/windows),同时赋变量path

path=os.path.join(BASE_DIR,path)

d.需要文件的名字,2.png是一个名字,但是也可以在某个目录下,如post|reid/2.png,要与base_dir拼接才是一个绝对路径,filename是要让服务器知道它重新写的文件的名称,server与client的文件名要统一,所以要把名称通知server端

filename=os.path.basename(path)  #参数是路径,可以取到文件名字

e.需要文件大小,通知server要接收文件的大小

file_size=os.stat(path).st_size

f.把内容打成一个包传输过去,还可以实现把文件存储在那个位置,没有可以创建目录,命令post,再加相应的内容,server端接收这种信息后,进行解释

file_info='post|%s|%s'%(filename,file_size)

g.把数据包传送到server

sk.sendall(bytes(file_info,'utf8'))

  

3. post_server到post_client内容进行接收
a. 接收数据

data=conn.recv(1024)

b.对数据解释,分配三个变量来解释

cmd,filename,filesze=str(data,'utf8').split('|')

c.加入相应的BASE_DIR,拼接路径

import os
BASE_DIR=os.path.dirname(os.path.abspath(__file__))

while True:
    conn, addr = sk.accept()
    while True:
        data=conn.recv(1024)
        cmd,filename,filesze=str(data,'utf8').split('|')
        path=os.path.join(BASE_DIR,'storage',filename)  
        ######storage已经固定,可以传过来后再拼接,BASE_DIR是当前文件的上级,storage同一路径的目录,filename文件名

d.把字符串类型的filesize转换成int类型

filesze=int(filesze)

  

4.post_client开始发送数据
a.打开文件,rb以bytes类型读,不加是以字符串的类型读

f=open(path,'rb')

b.读取文件,read是全部读取的,定义一次1024字节大小,发送一段段的发

data=f.read(1024)

c.判断什么时候把数据发完

    has_sent=0            #初始化发送的大小,has_sent已经发过去的内容,不能设置bytes
    while has_sent!=file_size:   #filez_size是int类型,has_sent也是
        data=f.read(1024)        #读数据
        sk.sendall(data)         #发送到server
        has_sent+=len(data)      #累加的是data的长度,has_sent是一个int整型,如果累加1024就要是它的倍数,有可能不是
    f.close()    
    print('upload success')

  

5.post_server进行接收数据
a.打开文件

f=open(path,'ab')

b.循环接收

        has_received=0                                 
        while has_received!=filesze:               
            data=conn.recv(1024)    #data是bytes类型
            f.write(data)           #直接写
            has_received+=len(data)
        f.close()

  

6.完整代码
[root@node2 file_upload]# cat post_client.py 

 1 #!/usr/local/python3/bin/python3
 2 import socket
 3 import os
 4 sk=socket.socket()
 5 address=('127.0.0.1',8888)
 6 sk.connect(address)
 7 
 8 BASE_DIR=os.path.dirname(os.path.abspath(__file__))    
 9 
10 while True:
11     inp=input('>>> ').strip()  # post | path
12     cmd,path=inp.split('|')                    
13     path=os.path.join(BASE_DIR,path)            
14     filename=os.path.basename(path)             
15     file_size=os.stat(path).st_size             
16     file_info='post|%s|%s'%(filename,file_size) 
17     sk.sendall(bytes(file_info,'utf8'))         
18     
19     f=open(path,'rb')  
20     data=f.read(1024) 
21     
22     has_sent=0            
23     while has_sent!=file_size:   
24         data=f.read(1024)
25         sk.sendall(data)
26         has_sent+=len(data)      
27     f.close()    
28     print('upload success')
29 
30 sk.close()
View Code

[root@node2 file_upload]# cat post_server.py

 1 #!/usr/local/python3/bin/python3
 2 import socket
 3 import subprocess
 4 import os
 5 # family type
 6 sk = socket.socket()
 7 address=('127.0.0.1',8888)
 8 sk.bind(address)
 9 sk.listen(3)
10 BASE_DIR=os.path.dirname(os.path.abspath(__file__))    
11 
12 while True:
13     conn, addr = sk.accept()
14     while True:
15         data=conn.recv(1024)                             
16         cmd,filename,filesze=str(data,'utf8').split('|')  
17         path=os.path.join(BASE_DIR,'file_upload',filename)         
18         filesze=int(filesze)                              
19         
20         f=open(path,'ab')                               
21         has_received=0                                 
22         while has_received!=filesze:               
23             data=conn.recv(1024)
24             f.write(data)   
25             has_received+=len(data)
26         f.close()
27         
28 sk.close()
View Code

 

7.测试

[root@node2 file_upload]#  python3 post_server.py 
waiting...
[root@node2 file_upload]# python3 post_client.py 
>>> post|2.png
[root@node2 py]# tree file_upload/
file_upload/
├── 2.png
├── post_client.py
├── post_server.py
└── storage
    └── 2.png

 

posted @ 2018-05-14 10:49  Reid21  阅读(792)  评论(0编辑  收藏  举报