python 网盘上传_python学习笔记 day32 实现网盘上传下载功能
1. 作業需求
借助socket模塊實現server端和client端的交互,擬實現網盤上傳下載的功能:
上傳: client端發送請求,把本地的文件上傳給server端,server端負責接收,然后server端的一個文件中寫入client端上傳的文件內容;
下載: client端發送請求,想要下載server端某文件,server端接收請求后,給客戶端發送該文件的內容(按字節讀取文件內容,然后邊讀邊發送給客戶端)
之前自己試著寫了一個:
1. 版本一(不完善--bymyself)
#server.py
importsocketimportpickle
sk=socket.socket()
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sk.bind(("127.0.0.1",8080))
sk.listen()
conn,addr=sk.accept()whileTrue:
head=conn.recv(1024)
head=pickle.loads(head)
file_name=head["filename"]
file_size=head["filesize"]
file_type=head["filetype"]
file_path=head["filepath"]
file_path=file_path+'\\'+file_name+'.'+file_type
with open(file_path,'wb') as f:while file_size>0:
content=conn.recv(1024)
f.write(content)
file_size-=1024conn.close()
sk.close()
View Code
#client.py
importsocketimportpickle
sk=socket.socket()
sk.connect(("127.0.0.1",8080))whileTrue:
head={"filename":"test","filesize":2048,"filetype":"txt",'filepath':"E:\pyhtonworkspace\py3-pratice\Pycharm_workspace\python_fullstack\week8\day07"}
file_size= head["filesize"]
head=pickle.dumps(head)
sk.send(head)
with open("xixi","rb") as f:while file_size>0:
content=f.read(1024)
sk.send(content)
file_size-=1024sk.close()
View Code
也可以實現上傳功能(其實就是client端發送一個請求,想把本地的某一個文件上傳給server端),server端可以接收這個文件,然后寫入,但是有一點點問題,到文件的最后 會多些一點亂七八糟的東西,這個問題沒有解決
2. 版本二(Eva-J)
#server.py
importsocketimportpickleimportstruct
sk=socket.socket()
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #防止重啟服務器發生錯誤
sk.bind(("127.0.0.1",8080)) #server端綁定IP地址和端口號
sk.listen()
conn,addr=sk.accept()
buffer=1024 #讀取文件的字節大小是1024
head_len_bytes=conn.recv(4) #因為client端需要發送head報頭的長度 int類型借助struct模板轉為byets類型發送,占有固定的長度四個字節
head_len=struct.unpack("i",head_len_bytes)[0] #把報頭head的字節長度 借助struct模塊轉為的bytes 再使用struct的unpack轉為int的整數,代表head報頭的字節長度
head_bytes=conn.recv(head_len) #字節類型,client端把報頭head使用pickle的dumps成bytes類型,直接發送,server直接接收head的bytes類型
head=pickle.loads(head_bytes) #把bytes類型的報頭head使用pickle反序列化為原來的字典類型
filesize=head["filesize"] #得到client端需要上傳的文件的長度
filename=head["filename"]+"."+head["filetype"] #得到client端需要上傳的文件的文件名
with open(filename,"wb") as f: #由于對于一些視頻,音頻等文件是無法按行讀的,所以需要使用按照直接讀,所以文件的打開方式都是rb 或者wb這種以二進制的方式進行的
while filesize>=0: #當還有需要讀取的字節數,就不斷地按照特定長度的字節讀取文件內容,然后寫到server端的同名文件中
if filesize>=buffer: #剩余的需要讀取的文件字節數大于buffer時 每次就按照buffer字節來讀
content=conn.recv(buffer)
f.write(content)
filesize-=bufferelse:
content=conn.recv(filesize)
f.write(content)
filesize-=buffer
conn.close()
sk.close()
#client.py
importsocketimportpickleimportstructimportos
sk=socket.socket()
sk.connect(("127.0.0.1",8080))
buffer=1024 #設置文件讀取的字節數
head={"filename":"2018ASID格式要求","filetype":"docx","filepath":r"F:\廈大課程-研二\研二上學期\2018ASID\格式要求","filesize":None} #定制報頭信息
filepath=os.path.join(head["filepath"],(head["filename"]+"."+head["filetype"])) #拼接路徑,其實就是所要上傳的文件路徑
filesize=os.path.getsize(filepath) #得到所要上傳的文件的字節數大小
head["filesize"]=filesize
head_bytes=pickle.dumps(head) #head想要從client端傳到server端,網絡傳輸必須序列化(pickle的結果時bytes,也可以使用json 序列化的結果是str)
head_bytes_len=len(head_bytes) #head報頭字節數的大小,因為網絡傳輸都是字節數,必須要告訴對方需要接收多少字節才能準確接收到該報頭信息
head_bytes_len_bytes=struct.pack("i",head_bytes_len) #把bytes類型的head 對應的字節長度這個整數int使用struct的pack模塊轉化為字節,都是對應四個字節#server端只需要接收四個字節,就可以拿到head字節數的長度,然后再接收這個 字節數的長度 就可以完全拿到head信息
sk.send(head_bytes_len_bytes) #發送head報頭字節數長度對應的字節(4個 里面其實代表的是表頭的長度信息)
sk.send(head_bytes) #接下來發送head報頭信息(字節類型的,server首先接收4個字節拿到head字節長度,接著接收這個字節長度 拿到head信息,bytes類型的,然后使用pickle反序列化成字典類型的head)
with open(filepath,'rb') as f: #打開filepath對應的文件---本地文件,,server端把需要上傳的本地文件 寫在py文件下的同名文件中
#由于視頻,音頻等文件需要按照字節來讀取文件,所以文件打開的方式是rb
while filesize>=0:if filesize>=buffer:
content=f.read(buffer) #讀的內容也是二進制,bytes類型
sk.send(content)
filesize-=bufferelse:
content=f.read(filesize)
sk.send(content)
filesize-=buffer
sk.close()
運行結果:
其實我只實現了上傳功能,下載的原理完全一樣的,直接把server 端和client端所做的工作互換就可以啦~
而且還可以加上比較人性化的交互功能,交給用戶選擇上傳還是下載,選擇路徑,文件名,這樣就顯得高大上啦~
總結
以上是生活随笔為你收集整理的python 网盘上传_python学习笔记 day32 实现网盘上传下载功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python垃圾回收机制原理_如何理解和
- 下一篇: python3 long类型_Pytho