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