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()
[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()
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