在python的socket編程中,可以實現上傳下載文件,並且在下載的時候,顯示進度條,具體的流程如下圖所示:
1、 服務器端代碼如下:
[root@python 519]# cat server.py #!/usr/bin/env python import time import SocketServer HOST = '192.168.1.60' PORT = 9999
#定義一個接收所有文件的方法,傳遞的參數為socket對象,文件名稱和文件大小 def recv_all(socketobj,file_name,file_size): f = open('/tmp/%s' % file_name,'w') while file_size > 0: if file_size <= 1024: data = socketobj.recv(1024) f.write(data) break elif file_size > 1024: data = socketobj.recv(1024) f.write(data) file_size -= 1024 f.close() class MyHandler(SocketServer.BaseRequestHandler): def handle(self): while True: #1.get the commands data = self.request.recv(1024) print data if data.strip() == 'exit' or not data:break options = data.strip().split(' ') if len(options) == 2: file_name = options[1] if options[0] == 'put': <span style="white-space:pre"> </span> #上傳文件的時候,將文件上傳到當前的路徑 #2.get the file size file_size = self.request.recv(1024) print file_size file_size = int(file_size) #3.get the file content recv_all(self.request,file_name,file_size) self.request.sendall('DONE')
<span style="white-space:pre"> </span>#在下載文件的時候,文件到TMP目錄中進行下載 elif options[0] == 'get': f = open('/tmp/%s' % file_name) data = f.read() self.request.send(str(len(data))) time.sleep(0.2) self.request.send(data) time.sleep(0.2) self.request.send('DONE') s = SocketServer.ThreadingTCPServer((HOST,PORT),MyHandler) print 'waiting for connection...' s.serve_forever()
在進行服務端編碼的時候,定義的規則是,上傳文件,那么就是將文件上傳到當前路徑中,如果是下載文件,那么會將文件保存在/tmp目錄下,並且使用傳送過來的名稱。
主要需要規定的是,在上傳時候,先接受客戶端上傳命令,也就是put 和文件名,然后接收到文件的大小,再接受文件的內容,當接受完畢之后,那么會發送給客戶端一個結束的信號,也就是DONE。,在進行上傳的時候,客戶端必須按照順序發送相關的數據,否則可能程序無法運行。
在下載的時候,先接受客戶端的下載命令,也就是get和文件名稱,然后服務器端直接發送所有的文件內容,發送內容之后,發送結束done,在進行連續發送的時候,可以看到使用了time的sleep函數,主要是用來防止粘包的產生,也就是發送數據的時候,數據先到達緩沖區,可能將這次和下次的數據一次性進行了發送,從而添加了sleep方法來等待發送,沒找到其他的更好的方法。
2、客戶端編碼如下:
[root@python 519]# cat client.py #!/usr/bin/env python import socket import time import processbar import time HOST = '192.168.1.60' PORT = 9999
#接收所有的數據文件,並且接收一次,寫入一次,從而避免內存消耗過大,在進行接收的時候,顯示進度條 def recv_all(socketobj,file_name,file_size): f = open(file_name,'w') while file_size > 0: if file_size <= 1024: processbar.progressbar(10,10) data = socketobj.recv(1024) f.write(data) break elif file_size > 1024: processbar.progressbar(1024*10/file_size,10) data = socketobj.recv(1024) f.write(data) file_size -= 1024 f.close() s = socket.socket() s.connect((HOST,PORT)) while True: commands = raw_input('>>>') if commands == 'exit' or not commands:break s.sendall(commands) options = commands.strip().split(' ') if len(options) == 2: file_name = options[1] if options[0] == 'put': f = open(file_name) data = f.read() time.sleep(0.2) s.send(str(len(data))) time.sleep(0.2) s.send(data) print s.recv(1024) elif options[0] == 'get': file_size = int(s.recv(1024)) recv_all(s,file_name,file_size) print s.recv(1024) else: pass
在進行客戶端接收的時候,如果是上傳,也就是先發送命令為put和f文件名稱,然后在發送文件的長度,再發送文件的內容,最后接收到服務器接收完畢的信號,也就是DOWN。
在進行下載的時候,先發送命令為get和文件名稱,然后得到文件的大小,再調用方法接收所有的文件,並且顯示進度條
進度條的代碼可以參考上篇文章,也就是直接導入進度條的代碼即可。
在進行接收文件的時候,每次接收1024個字節,然后根據循環判斷剩余的文件大小,每次接收1024個字節。
在顯示進度條的時候,主要就是定義的顯示的進度個數為十個,從而在顯示的使用的計算方式是:
size/*10file_size,從而得到上傳的進度。