在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,從而得到上傳的進度。
