FTP上传文件服务器python实现
总结
使用Python的socket和socketserver模块实现ftp文件服务器。不是很难,但在粘包的问题上纠缠了不少时间。解决办法是发送文件信息之后等待一段时间。
1 #!/usr/bin/python 2 #coding:utf-8 3 ''' 4 ftp文件上传 服务器端 5 ''' 6 7 import socketserver 8 import os 9 10 11 class myFtpServer(socketserver.BaseRequestHandler): 12 def setup(self): 13 pass 14 15 def handle(self): 16 dir = r'F:\temp' #存放接收文件的目录 17 18 print('Connected %s:%d' %self.client_address) 19 while True: #持续接收文件 20 #接收文件的名称和大小 21 fileInfo = self.request.recv(1024) 22 if fileInfo.decode('utf-8') == 'exit': 23 break 24 filename, filesize = fileInfo.decode('utf-8').strip().split('|') 25 filePath = os.path.join(dir, filename) #创建文件存放路径 26 print('Receiving file:%s, filesize:%s'%(filename, filesize)) 27 with open(filePath, 'wb') as f: 28 recvsize = 0 29 while True: #持续接收文件内容 30 if recvsize == int(filesize): #当接收的大小与文件大小相等时结束接收 31 break 32 self.data = self.request.recv(1024) 33 recvsize += len(self.data) 34 f.write(self.data) 35 print('upload succeed!!') 36 print(recvsize) 37 print('Disconnected %s:%d.' %self.client_address) 38 ''' 39 def handle(self): 40 base_path = '' 41 conn = self.request 42 print( 'connected...') 43 while True: 44 pre_data = conn.recv(1024) 45 #获取请求方法、文件名、文件大小 46 file_name,file_size = pre_data.decode('utf-8').split('|') 47 48 #已经接收文件的大小 49 recv_size = 0 50 #上传文件路径拼接 51 file_dir = os.path.join(base_path,file_name) 52 f = open(file_dir,'wb') 53 Flag = True 54 while Flag: 55 #未上传完毕, 56 if int(file_size)>recv_size: 57 #最多接收1024,可能接收的小于1024 58 data = conn.recv(1024) 59 recv_size+=len(data) 60 #上传完毕,则退出循环 61 else: 62 recv_size = 0 63 Flag = False 64 #写入文件 65 f.write(data) 66 print('upload successed.') 67 f.close() 68 def finish(self): 69 pass 70 71 ''' 72 if __name__ == '__main__': 73 addr = ('127.0.0.1', 9999) 74 sk = socketserver.ThreadingTCPServer(addr, myFtpServer) 75 sk.serve_forever()
1 #!/usr/bin/python 2 #coding:utf-8 3 ''' 4 ftp文件上传 客户端 5 ''' 6 import socket 7 import sys 8 import os 9 import time 10 11 def ftp(address): 12 sk = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) 13 sk.connect(address) 14 while True: 15 #filePath = r'C:\Users\admin\Desktop\test' 16 filePath = input('Input file path:') 17 if filePath == 'exit': #判断退出 18 sk.send(b'exit') 19 break 20 if not os.path.isfile(filePath): #判断是否文件 21 print('Not available file path...') 22 continue 23 filename = os.path.basename(filePath) 24 #dir = os.path.dirname(filePath) 25 26 filesize = os.stat(filePath).st_size #获取文件大小 27 fileInfo = '%s|%s'%(filename, filesize) #重新组织文件信息,包括文件名和文件大小,用‘|’分割 28 29 #发送文件信息 30 sk.send(fileInfo.encode(encoding='utf-8', errors='strict')) 31 time.sleep(0.01) #为了防止粘包,在文件信息发送之后等待0.01秒 32 33 #持续发送文件内容 34 with open(filePath, 'rb') as f: 35 sendsize = 0 36 flag = True 37 while flag: 38 if sendsize + 1024 > filesize: #判断最后一份文件内容的读取 39 data = f.read(filesize - sendsize) 40 flag = False 41 else: #一般文件内容的读取 42 data = f.read(1024) 43 sendsize += 1024 44 sk.send(data) 45 46 sk.close() 47 48 if __name__ == '__main__': 49 addr = ('127.0.0.1',9999) 50 ftp(addr)
环境:python3.5 win10 x64