TCP簡單實現文件上傳與下載


服務器端:

 1 import socket  2 from ms.login import read  3 from ms.login import down  4 from ms.login import up  5 
 6 buffer=1024  #一次讀取內容長度字節
 7 sk=socket.socket()   #創建socket對象
 8 sk.bind(('127.0.0.1',8080))  #綁定地址
 9 sk.listen()  #監聽
10 
11 conn,addr=sk.accept() #建立一個連接
12 
13 info=conn.recv(50).decode('utf-8')   #接收客戶端的用戶名密碼
14 user,psd=info.split('|')   #分割獲取用戶名 和 密碼
15 
16 ret=read(user,psd)  #調read讀取用戶名信息 驗證用戶名密碼是否正確
17 if ret:  #登錄成功
18     conn.send(bytes('ok'.encode('utf-8')))   #返回一個OK
19     conn.send(bytes('用戶登錄成功,請選擇要執行的操作【U:上傳文件】【D:下載文件】'.encode('utf-8'))) 20 
21     choice=conn.recv(4).decode('utf-8')   #客戶端選擇上傳還是下載
22 
23     if choice=='U':  #文件上傳
24         up(conn,buffer)    #調上傳方法
25 
26     elif choice=='D':   # 文件下載
27         down(conn)  #調下載方法
28     else: 29         print('error,錯誤的操作指令!') 30 else:   #登錄失敗 關閉連接和對象
31     conn.send(bytes('用戶登錄失敗,斷開連接...'.encode('utf-8'))) 32  conn.close() 33     sk.close()

 

 

調用函數的模塊:

 1 import os  2 import struct  3 import operator  4 import time  5 import json  6 
 7 
 8 #登錄驗證
 9 def read(user,psd): 10     with open('info','r',encoding='utf-8')as f: 11         for i in f:     #讀取所有記錄
12             i=i.strip()     #去空格
13             if user in i:   #如果用戶名相匹配
14                 n_user,n_psd=i.split('|')     #分割字符串 得到用戶名密碼
15                 if n_psd==psd: 16                     return True     #密碼正確則為TRUE
17                 else: 18                     return False    #錯誤則為FALSE
19 #上傳
20 def up(conn,buffer): 21     long=conn.recv(4)   #4字節的數據長度包
22     pack_long=struct.unpack('i',long)[0]  #報頭的長度
23     filejson=conn.recv(pack_long).decode('utf-8') 24     fileinfo=json.loads(filejson) #報頭內容
25 
26     filename = fileinfo['filename'] 27     filesize = fileinfo['filesize'] 28 
29     with open(filename, 'wb')as f:  #將接收到的數據寫入文件
30         while filesize: 31             if filesize >= buffer:   #如果文件大小 大於讀取數據量
32                 filedata = conn.recv(buffer) 33                 f.write(filedata)     #就將讀取的數據量寫入
34                 filesize -= buffer 35             else: 36                 filedata = conn.recv(filesize) 37                 f.write(filedata)    #直接把文件寫入
38                 break
39         print('文件%s上傳成功' % filename) 40 
41 
42 #下載
43 def down(conn): 44     files = os.listdir() 45     lis_file = ''
46     for i in files: 47         lis_file += i + '\n'
48     if operator.eq(lis_file, ''):  # 如果文件列表為空
49         conn.send(''.encode('utf-8')) 50     else: 51         conn.send(lis_file.encode('utf-8'))  #把文件列表發給客戶端
52         while True: 53             filename=conn.recv(1024).decode('utf-8')  #接收要下載的文件名
54             if filename not in files: 55                 conn.send(bytes('文件名不存在!'.encode('utf-8'))) 56             else: 57                 conn.send(bytes('開始文件傳輸!'.encode('utf-8'))) 58                 break
59         size=os.stat(filename).st_size 60         info=struct.pack('i',size) 61         conn.send(info)    #文件信息大小打包發送給客戶端
62 
63         with open(filename,'rb')as f: 64             while True: 65                 file_data=f.read(4096) 66                 if not file_data: 67                     break
68  conn.send(file_data) 69 
70         show='{0}\n下載文件:{1}:\n{2}byte\nSuccessful...\n\n'.format(time.strftime('%Y-%m-%d:%H:%M:%S',time.localtime(time.time())),filename,size) 71         print(show) 72         path=os.path.dirname(os.path.abspath(__file__)) 73         path=os.path.join(path,'log') 74 
75         os.chdir(path)    #臨時把當前目錄變為 E:\program\ms\log
76         with open('data_log','a',encoding='utf-8')as f: 77             f.write(show)              #把輸出信息記錄入日志

 

客戶端:

 1 import socket  2 import struct  3 import os,sys  4 import operator  5 import time  6 import json  7 
 8 buffer=1024
 9 
10 sk=socket.socket() 11 sk.connect(('127.0.0.1',8080)) 12 user=input('請輸入用戶名:') 13 psd=input('請輸入密碼:') 14 login=str(user)+'|'+str(psd) 15 sk.send(bytes(login.encode('utf-8')))  #傳用戶名密碼給客戶端
16 ret=sk.recv(1024).decode('utf-8')   #接收登錄狀態 ok
17 
18 if ret=='ok': 19     menu=sk.recv(1024).decode('utf-8') 20     print(menu)              #顯示操作菜單
21     do=input('請輸入要執行的操作...').upper() 22     sk.send(bytes(do.encode('utf-8')))    #輸入上傳還是下載
23 
24     #選擇上傳
25     if do=='U': 26         filepath = input('請輸入要上傳的文件路徑\n') 27         filename = input('請輸入文件名\n') 28 
29         path = os.path.join(filepath, filename) 30         filesize = os.stat(path).st_size  # 文件大小
31         fileinfo = {'filename': filename, 'filepath': filepath,'filesize':filesize} 32         filejson=json.dumps(fileinfo).encode('utf-8') 33         long=len(filejson) #報頭的長度
34         pack_long=struct.pack('i',long)  #報頭長度變為4字節
35  sk.send(pack_long) 36  sk.send(filejson) 37 
38         with open(path, 'rb')as f: 39             while filesize: 40                 if filesize >= 1024: 41                     filedata = f.read(buffer) 42  sk.send(filedata) 43                     filesize -= buffer 44                 else: 45                     filedata = f.read(filesize) 46  sk.send(filedata) 47                     break
48 
49         show = '{0}\n上傳文件:{1}:\n{2}byte\nSuccessful...\n\n'.format( 50             time.strftime('%Y-%m-%d:%H:%M:%S', time.localtime(time.time())), filename,filesize) 51         print(show) 52 
53 
54     # 選擇下載
55     elif do=='D': 56         r=sk.recv(1024).decode('utf-8')   #收到文件列表
57         if operator.eq(r,''): 58             print('沒有可以下載的文件') 59         print(r) 60         filename= input('請輸入要下載的文件名>>>') 61         sk.send(bytes(filename.encode('utf-8')))   #發送要下載的文件名
62         state=sk.recv(1024).decode('utf-8')  #文件下載狀態
63         print(state) 64 
65         info=sk.recv(4)   #4字節的包
66         size=struct.unpack('i',info)[0]  #文件的字節大小
67         print(filename,size) 68 
69         data=sk.recv(size).decode('utf-8') 70 
71         path = os.path.dirname(os.path.abspath(__file__)) 72         path = os.path.join(path, 'down') 73  os.chdir(path) 74         with open(filename,'w+',encoding='utf-8')as f: 75  f.write(data) 76         print(data) 77 
78     else: 79         print('error,錯誤的操作指令!') 80 
81 
82 sk.close()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM