def auth(self, instructions): ''' 用户认证方法,默认用户为guest用户,认证成功后切换用户 :param instructions: 客户端指令 :return: 无 ''' import json import os res = json.loads(instructions[1]) user = self.__users.get_user(res['username']) # 通过用户名获取用户信息 # 判断用户是否存在 if user: # 判断密码是否正确 print(user.get_password()) if user.get_password() == res['password']: # 如果验证当前用户等于认证成功的用户 self.__current_user = user # 当前目录等于用户的家目录 self.__current_path = os.path.abspath(os.path.join(conf.HOME_PATH,self.__current_user.get_username())).replace('\\', '/') # 告诉客户端用户成功 self.request.sendall(mylib.s2b('200')) self.__loger.info('%s from [%s]' %(self.__code_list['200'], self.client_address)) else: self.request.sendall(mylib.s2b('201')) self.__loger.error('%s from [%s]' %(self.__code_list['201'], self.client_address)) else: self.request.sendall(mylib.s2b('201')) self.__loger.error('%s from [%s]' %(self.__code_list['201'], self.client_address))
def cd(self, client_cmd): ''' cd方法,用于服务端目录切换 :param client_cmd: 用户命令 :return: 无 ''' path = client_cmd[1] # 获取cd的目录 import os if path == '.': # 如果目录是.说明是当前目录,啥也不干 pass elif path == '..': # 如果是.., 说明是父目录 # 判断当前目录是不是已经是家目录,也就是根目录,若果是啥也不干,如果不是,进入到上一级目录 if self.__current_path == self.__current_user['home']: self.request.sendall(mylib.s2b('ok')) else: self.__current_path = os.path.split(self.__current_path[0:len(self.__current_path)-1])[0] + '/' print(os.path.split(self.__current_path[0:len(self.__current_path)-1])) self.request.sendall(mylib.s2b('ok')) elif path == '/' or path == '~': # 如果是/或者~ 表示进入到家目录,当前目录等于用户的家目录 self.__current_path = self.__current_user['home'] self.request.sendall(mylib.s2b('ok')) else: # 其他情况,先判断目录是否合法,合法当前目录等于拼接后的目录,否则通知客户端目录不存在 if os.path.isdir(self.__current_path + path): self.__current_path += path + '/' self.request.sendall(mylib.s2b('ok')) else: self.request.sendall(mylib.s2b('目录%s不存在' %path))
def cd(self, client_cmd): ''' cd方法,用于服务端目录切换 :param client_cmd: 用户命令 :return: 无 ''' path = client_cmd[1] # 获取cd的目录 import os if path == '.': # 如果目录是.说明是当前目录,啥也不干 pass elif path == '..': # 如果是.., 说明是父目录 # 判断当前目录是不是已经是家目录,也就是根目录,若果是啥也不干,如果不是,进入到上一级目录 if self.__current_path == self.__current_user['home']: self.request.sendall(mylib.s2b('ok')) else: self.__current_path = os.path.split( self.__current_path[0:len(self.__current_path) - 1])[0] + '/' print(os.path.split( self.__current_path[0:len(self.__current_path) - 1])) self.request.sendall(mylib.s2b('ok')) elif path == '/' or path == '~': # 如果是/或者~ 表示进入到家目录,当前目录等于用户的家目录 self.__current_path = self.__current_user['home'] self.request.sendall(mylib.s2b('ok')) else: # 其他情况,先判断目录是否合法,合法当前目录等于拼接后的目录,否则通知客户端目录不存在 if os.path.isdir(self.__current_path + path): self.__current_path += path + '/' self.request.sendall(mylib.s2b('ok')) else: self.request.sendall(mylib.s2b('目录%s不存在' % path))
def put(self, instructions): ''' put方法 :param instructions: 客户端指令 :return: 无 ''' import os import json res = json.loads(instructions[1]) file_name = os.path.join(self.__current_path, res['filename']) # 获取上传的文件名 md5 = res['md5'] # 获取上传的文件的md5 tmp_file_name = os.path.join(self.__current_path, '%s.ftp' %res['filename']) # 定义临时文件 if os.path.isfile(tmp_file_name): # 判断临时文件,如果存在说明没传完,将续传 tmp_file_size = os.path.getsize(tmp_file_name) # 获取已经上传的大小 else: tmp_file_size = 0 self.request.send(mylib.s2b(r'ready|{"recv_size":%s}' %tmp_file_size)) # 通知客户端准备上传并返回已近上传的大小 recv_size = tmp_file_size file_size = res['file_size'] f = open(tmp_file_name, 'ab') self.__loger.info('Begin recv file %s from client [%s]' %(file_name, self.client_address)) while recv_size != file_size: # 只要已上传的大小不等于文件的大小就循环获取数据写入文件 try: data = self.request.recv(conf.FILE_PER_SIZE) recv_size += len(data) f.write(data) mylib.process_bar(recv_size, file_size) except socket.error as e: print(self.__code_list['306']) f.close() break except IOError as e: print(self.__code_list['305']) f.close() break f.close() self.__loger.info('End recv file %s from client [%s]' %(file_name, self.client_address)) new_md5 = mylib.get_file_md5(tmp_file_name) # 获取上传后的md5值 self.__loger.info('Begin validate md5 [%s]' %tmp_file_name) if new_md5 == md5: # 验证md5,成功则将临时文件名改为正式文件名 import shutil shutil.move(tmp_file_name, file_name) self.request.sendall(mylib.s2b('308')) self.__loger.info('%s %s' %(self.__code_list['308'], tmp_file_name)) else: os.remove(tmp_file_name) self.request.sendall(mylib.s2b('309')) self.__loger.info('%s %s' %(self.__code_list['309'], tmp_file_name)) self.__loger.info('End validate md5 [%s]' %tmp_file_name)
def checkspacesize(self, client_cmd): ''' 检查剩余空间是否可以上传文件方法 :param client_cmd: 用户命令 :return: 无 ''' file_size = int(client_cmd[1]) # 获取文件大小 # 获取剩余空间大小 free_size = int(self.__current_user['max_size'] - mylib.get_dir_size_for_linux(self.__current_path)) # 判断剩余空间是否够,如果够告诉客户端can,如果不够告诉客户端not if file_size < free_size: self.request.sendall(mylib.s2b('can')) else: self.request.sendall(mylib.s2b('not'))
def put(self, client_cmd): ''' 上传文件方法 :param client_cmd: 客户端命令 :return: 无 ''' import os import shutil # 拼接要上传的文件名 print(client_cmd) filename = self.__current_path + os.path.split(client_cmd[1])[1] file_size = int(client_cmd[2]) #filename = os.path.split(filename)[1] md5 = client_cmd[3] # 从客户端命令中获取文件的md5值,稍后用于比对 # 定义临时文件 tmp_filename = '%s.ftp' %filename # 判断临时文件是否存在,如果存在获取临时文件的大小,传给客户端,端点续传 if os.path.isfile(tmp_filename): tmp_file_size = os.path.getsize(tmp_filename) else: tmp_file_size = 0 self.request.sendall(mylib.s2b('put|ready|%s' %tmp_file_size)) Confirm = mylib.b2s(self.request.recv(100)) recv_size = tmp_file_size if Confirm.startswith('put|ready'): # 判断是否是续传,如果是续传文件以追加的形式打开,如果不是则以写的方式打开 if recv_size == 0: f = open('%s.ftp' %filename, 'wb') else: f = open('%s.ftp' %filename, 'ab') # 接收文件知道传输结束 while file_size != recv_size: data = self.request.recv(conf.FILE_PER_SIZE) # 如果传输中断,退出整个方法,这里用到了一个技巧,return一个None,强制结束 if len(data) == 0: f.close() return None recv_size += len(data) f.write(data) f.close() # 对比文件md5值如果相同降临时文件重命名,否则删除 new_md5 = mylib.get_file_md5('%s.ftp' %filename) if md5 == new_md5: shutil.move('%s.ftp' %filename, filename) self.request.sendall(mylib.s2b('上传成功')) else: os.remove(tmp_filename) self.request.sendall(mylib.s2b('上传失败'))
def put(self, client_cmd): ''' 上传文件方法 :param client_cmd: 客户端命令 :return: 无 ''' import os import shutil # 拼接要上传的文件名 print(client_cmd) filename = self.__current_path + os.path.split(client_cmd[1])[1] file_size = int(client_cmd[2]) #filename = os.path.split(filename)[1] md5 = client_cmd[3] # 从客户端命令中获取文件的md5值,稍后用于比对 # 定义临时文件 tmp_filename = '%s.ftp' % filename # 判断临时文件是否存在,如果存在获取临时文件的大小,传给客户端,端点续传 if os.path.isfile(tmp_filename): tmp_file_size = os.path.getsize(tmp_filename) else: tmp_file_size = 0 self.request.sendall(mylib.s2b('put|ready|%s' % tmp_file_size)) Confirm = mylib.b2s(self.request.recv(100)) recv_size = tmp_file_size if Confirm.startswith('put|ready'): # 判断是否是续传,如果是续传文件以追加的形式打开,如果不是则以写的方式打开 if recv_size == 0: f = open('%s.ftp' % filename, 'wb') else: f = open('%s.ftp' % filename, 'ab') # 接收文件知道传输结束 while file_size != recv_size: data = self.request.recv(conf.FILE_PER_SIZE) # 如果传输中断,退出整个方法,这里用到了一个技巧,return一个None,强制结束 if len(data) == 0: f.close() return None recv_size += len(data) f.write(data) f.close() # 对比文件md5值如果相同降临时文件重命名,否则删除 new_md5 = mylib.get_file_md5('%s.ftp' % filename) if md5 == new_md5: shutil.move('%s.ftp' % filename, filename) self.request.sendall(mylib.s2b('上传成功')) else: os.remove(tmp_filename) self.request.sendall(mylib.s2b('上传失败'))
def rm(self, instructions): ''' 删除文件方法 :param cliend_cmd: 用户命令 :return: 无 ''' import json import os import shutil res = json.loads(instructions[1]) filename = os.path.join(self.__current_path, res['path']) if self.__check_path(filename): if os.path.isdir(filename):# 如果是目录递归删除目录 shutil.rmtree(filename) response_code = '500' elif os.path.isfile(filename): # 如果是文件,只删除文件 os.remove(filename) response_code = '500' self.__loger.info('%s to rm %s' %(self.__code_list['500'], filename)) else: # 其他情况说明文件或目录不存在 #self.request.sendall(mylib.s2b('310')) response_code = '310' self.__loger.info('%s to rm %s' %(self.__code_list['310'], filename)) self.request.send(mylib.s2b('{"code":"%s"}' %response_code)) # 返回错误码
def pwd(self, client_cmd): ''' 获取当前目录方法 :param client_cmd: 用户命令 :return: ''' # 将当前目录告诉客户端 self.request.sendall(mylib.s2b(self.__current_path))
def get(self, user_input): ''' 客户端下载方法 :param user_input: 用户输入的指令 :return: 无 ''' import os if len(user_input) == 2: # 如果是get xxx,则表示下载到当前目录 dst_path = '.' elif len(user_input) == 3: # 如果是 get xxx xxx,则表示要下载到其他目录 dst_path = user_input[2] else: print(self.__code_list['401']) return None if os.path.isdir(dst_path): # 判断目标文件是否存在 filename = user_input[1] # 获取下载的文件名 tmp_filename = os.path.join(self.__tmp_path, '%s.ftp' % os.path.split(filename)[1]) # 定义临时文件 if os.path.isfile(tmp_filename): # 判断临时文件是否存在(也就是是否需要续传) tmp_file_size = os.path.getsize(tmp_filename) # 获取临时文件的大小 else: tmp_file_size = 0 self.__sk.send( mylib.s2b(r'get|{"filename":"%s", "sendsize": %s}' % (filename, tmp_file_size))) # 向服务端发送下载指令接文件名和已近下载的大小 Confirm = mylib.b2s(self.__sk.recv(100)).split('|') # 获取服务器反馈 if Confirm[0] == 'ready': # 如果是ready则准备下载文件 file_size = json.loads(Confirm[1])['filesize'] # 获取文件大小 md5 = json.loads(Confirm[1])['md5'] # 获取md5 recv_size = tmp_file_size f = open(tmp_filename, 'ab') while file_size != recv_size: # 只要已下载大小不等于文件大小则循环接受数据 try: data = self.__sk.recv(conf.FILE_PER_SIZE) recv_size += len(data) f.write(data) mylib.process_bar(recv_size, file_size) except socket.error as e: print(self.__code_list['306']) f.close() break except IOError as e: print(self.__code_list['305']) f.close() print('') print('Validating...') new_md5 = mylib.get_file_md5(tmp_filename) if new_md5 == md5: # 验证md5,如果验证通过修改成正式文件名,如果没验证过去删除临时文件 import shutil shutil.move(tmp_filename, os.path.join(dst_path, filename)) else: os.remove(tmp_filename) else: print(self.__code_list[Confirm[1]]) else: print(self.__code_list['304'])
def put(self, user_input): ''' 客户端上传方法 :param user_input: 指令 :return: 无 ''' import json if len(user_input) == 2: file_name = user_input[1] if not os.path.isfile(file_name): print(self.__code_list['302']) return None self.__sk.sendall(mylib.s2b('checkspacesize')) res = json.loads(mylib.b2s(self.__sk.recv(100))) free_size = int(res['freesize']) * 1024 * 1024 # 获取剩余空间大小 file_size = os.path.getsize(file_name) if free_size > file_size: # 判断剩余空间是否够,够就下载,不够就直接返回 md5 = mylib.get_file_md5(file_name) # 获取上传文件的md5 self.__sk.send( mylib.s2b( r'put|{"filename":"%s", "file_size":%s, "md5":"%s"}' % (os.path.split(file_name)[1], file_size, md5))) # 发送上传指令,并通知服务端文件名,文件大小和md5 res = mylib.b2s(self.__sk.recv(200)).split('|') # 获取服务端确认信息 if res[0] == 'ready': send_size = json.loads(res[1])['recv_size'] # 获取已经上传的大小 f = open(file_name, 'rb') f.seek(send_size) # 设定文件的其实位置为已上传的大小 while file_size != send_size: # 只要文件大小不等于上传的大小则循环读文件并上传数据 if file_size - send_size > conf.FILE_PER_SIZE: data = f.read(conf.FILE_PER_SIZE) send_size += conf.FILE_PER_SIZE else: data = f.read(file_size - send_size) send_size += (file_size - send_size) self.__sk.send(data) mylib.process_bar(send_size, file_size) print(mylib.b2s(self.__sk.recv(200))) print("") else: print(self.__code_list['307']) else: print(self.__code_list['401'])
def move(self, cliend_cmd): ''' 移动文件或重命名文件方法 :param cliend_cmd: 用户命令 :return: ''' import shutil import os # 获取旧的文件名 filename = self.__current_path + cliend_cmd[1] # 获取新的文件名 new_filename = self.__current_path + cliend_cmd[2] if filename.startswith('~') or filename.startswith('/') or filename.startswith('..') or new_filename.startswith('~') or new_filename.startswith('/') or new_filename.startswith('..'): self.request.sendall(mylib.s2b('目录不合法')) elif os.path.isfile(filename) or os.path.isdir(filename): # 旧的文件或目录存在执行move shutil.move(filename, new_filename) self.request.sendall(mylib.s2b('ok')) else: # 否则告诉客户端目录或文件不存在 self.request.sendall(mylib.s2b('目录或文件%s不存在' %filename))
def get(self, user_input): ''' 客户端下载方法 :param user_input: 用户输入的指令 :return: 无 ''' import os if len(user_input) == 2: # 如果是get xxx,则表示下载到当前目录 dst_path = '.' elif len(user_input) == 3: # 如果是 get xxx xxx,则表示要下载到其他目录 dst_path = user_input[2] else: print(self.__code_list['401']) return None if os.path.isdir(dst_path): # 判断目标文件是否存在 filename = user_input[1] # 获取下载的文件名 tmp_filename = os.path.join(self.__tmp_path,'%s.ftp' %os.path.split(filename)[1]) # 定义临时文件 if os.path.isfile(tmp_filename): # 判断临时文件是否存在(也就是是否需要续传) tmp_file_size = os.path.getsize(tmp_filename) # 获取临时文件的大小 else: tmp_file_size = 0 self.__sk.send(mylib.s2b(r'get|{"filename":"%s", "sendsize": %s}' %(filename, tmp_file_size))) # 向服务端发送下载指令接文件名和已近下载的大小 Confirm = mylib.b2s(self.__sk.recv(100)).split('|') # 获取服务器反馈 if Confirm[0] == 'ready': # 如果是ready则准备下载文件 file_size = json.loads(Confirm[1])['filesize'] # 获取文件大小 md5 = json.loads(Confirm[1])['md5'] # 获取md5 recv_size = tmp_file_size f = open(tmp_filename, 'ab') while file_size != recv_size: # 只要已下载大小不等于文件大小则循环接受数据 try: data = self.__sk.recv(conf.FILE_PER_SIZE) recv_size += len(data) f.write(data) mylib.process_bar(recv_size, file_size) except socket.error as e: print(self.__code_list['306']) f.close() break except IOError as e: print(self.__code_list['305']) f.close() print('') print('Validating...') new_md5 = mylib.get_file_md5(tmp_filename) if new_md5 == md5: # 验证md5,如果验证通过修改成正式文件名,如果没验证过去删除临时文件 import shutil shutil.move(tmp_filename, os.path.join(dst_path, filename)) else: os.remove(tmp_filename) else: print(self.__code_list[Confirm[1]]) else: print(self.__code_list['304'])
def rm(self, user_input): ''' 删除文件方法 :param user_input: 用户命令 :return: 无 ''' if len(user_input) == 2: self.__sk.send(mylib.s2b('rm|{"path" : "%s"}' %user_input[1])) # 向服务端发送删除指令 res = json.loads(mylib.b2s(self.__sk.recv(200))) # 获取执行结果(错误码) print(self.__code_list[res['code']]) else: print(self.__code_list['401'])
def auth(self, client_cmd): ''' 认证用户方法 :param client_cmd: 用户命令 :return: 无 ''' user = self.__userobj.get_user(client_cmd[1]) # 通过用名获取用户信息 # 判断用户是否存在 if user: # 判断密码是否正确 if user['password'] == client_cmd[2]: # 如果验证当前用户等于认证成功的用户 self.__current_user = user # 当前目录等于用户的家目录 self.__current_path = user['home'] # 告诉客户端用户成功 self.request.sendall(mylib.s2b('ok')) else: self.request.sendall(mylib.s2b('fail')) else: self.request.sendall(mylib.s2b('fail'))
def rm(self, cliend_cmd): ''' 删除文件方法 :param cliend_cmd: 用户命令 :return: 无 ''' filename = self.__current_path + cliend_cmd[1] # 获取要删除的文件 import os import shutil if filename.startswith('~') or filename.startswith('/') or filename.startswith('..'): # 目录不合法 self.request.sendall('目录不合法') elif os.path.isdir(filename):# 如果是目录递归删除目录 shutil.rmtree(filename) self.request.sendall(mylib.s2b('ok')) elif os.path.isfile(filename): # 如果是文件,只删除文件 os.remove(filename) self.request.sendall(mylib.s2b('ok')) else: # 其他情况说明文件或目录不存在 self.request.sendall(mylib.s2b('目录或文件%s不存在' %filename))
def put(self, user_input): ''' 客户端上传方法 :param user_input: 指令 :return: 无 ''' import json if len(user_input) == 2: file_name = user_input[1] if not os.path.isfile(file_name): print(self.__code_list['302']) return None self.__sk.sendall(mylib.s2b('checkspacesize')) res = json.loads(mylib.b2s(self.__sk.recv(100))) free_size = int(res['freesize']) * 1024 * 1024 # 获取剩余空间大小 file_size = os.path.getsize(file_name) if free_size > file_size: # 判断剩余空间是否够,够就下载,不够就直接返回 md5 = mylib.get_file_md5(file_name) # 获取上传文件的md5 self.__sk.send(mylib.s2b(r'put|{"filename":"%s", "file_size":%s, "md5":"%s"}' %(os.path.split(file_name)[1], file_size, md5))) # 发送上传指令,并通知服务端文件名,文件大小和md5 res = mylib.b2s(self.__sk.recv(200)).split('|') # 获取服务端确认信息 if res[0] == 'ready': send_size = json.loads(res[1])['recv_size'] # 获取已经上传的大小 f = open(file_name, 'rb') f.seek(send_size) # 设定文件的其实位置为已上传的大小 while file_size != send_size: # 只要文件大小不等于上传的大小则循环读文件并上传数据 if file_size - send_size > conf.FILE_PER_SIZE: data = f.read(conf.FILE_PER_SIZE) send_size += conf.FILE_PER_SIZE else: data = f.read(file_size - send_size) send_size += (file_size - send_size) self.__sk.send(data) mylib.process_bar(send_size, file_size) print(mylib.b2s(self.__sk.recv(200))) print("") else: print(self.__code_list['307']) else: print(self.__code_list['401'])
def __runcmd(self, cmd): ''' 执行原生shell命令方法 :param cmd: 命令 :return: ''' cmd_call = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) cmd_result = cmd_call.stdout.read() ack_msg = mylib.s2b("CMD_RESULT_SIZE|%s" %len(cmd_result)) self.request.send(ack_msg) client_ack = self.request.recv(50) if client_ack.decode() == 'CLIENT_READY_TO_RECV': self.request.send(cmd_result)
def __runcmd(self, cmd): ''' 执行原生shell命令方法 :param cmd: 命令 :return: ''' cmd_call = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) cmd_result = cmd_call.stdout.read() ack_msg = mylib.s2b("CMD_RESULT_SIZE|%s" % len(cmd_result)) self.request.send(ack_msg) client_ack = self.request.recv(50) if client_ack.decode() == 'CLIENT_READY_TO_RECV': self.request.send(cmd_result)
def rm(self, user_input): ''' 删除文件方法 :param user_input: 用户命令 :return: 无 ''' if len(user_input) == 2: self.__sk.send(mylib.s2b('rm|{"path" : "%s"}' % user_input[1])) # 向服务端发送删除指令 res = json.loads(mylib.b2s(self.__sk.recv(200))) # 获取执行结果(错误码) print(self.__code_list[res['code']]) else: print(self.__code_list['401'])
def get(self, client_cmd): ''' 下载文件方法 :param client_cmd: 分割后的命令 :return: 无 ''' #print(client_cmd) import os # 拼接目录和文件名 filename = self.__current_path + client_cmd[1] # 判断文件是否存在 if os.path.isfile(filename): # 获取文件的md5 md5 = mylib.get_file_md5(filename) # 获取文件大小 file_size = os.path.getsize(filename) # 将文件的的大小,md5以及文件准备就绪的信息通知客户端 res = "get|ready|%s|%s" % (file_size, md5) self.request.sendall(mylib.s2b(res)) f = open(filename, 'rb') # 获取已经传输的文件大小 send_size = int(client_cmd[2]) # 定位文件的位置,用于断电续传 f.seek(send_size) # 判断文件是否传输完毕 while file_size != send_size: # 传输读取文件内容并传输,如果剩余大小每次传输的大小,则传输固定大小,如果剩余的大小 if file_size - send_size > conf.FILE_PER_SIZE: data = f.read(conf.FILE_PER_SIZE) send_size += conf.FILE_PER_SIZE else: data = f.read(file_size - send_size) send_size += (file_size - send_size) self.request.sendall(data) #print(file_size, send_size) else: res = "文件%s不存在" % filename self.request.sendall(mylib.s2b(res))
def get(self, client_cmd): ''' 下载文件方法 :param client_cmd: 分割后的命令 :return: 无 ''' #print(client_cmd) import os # 拼接目录和文件名 filename = self.__current_path + client_cmd[1] # 判断文件是否存在 if os.path.isfile(filename): # 获取文件的md5 md5 = mylib.get_file_md5(filename) # 获取文件大小 file_size = os.path.getsize(filename) # 将文件的的大小,md5以及文件准备就绪的信息通知客户端 res = "get|ready|%s|%s" %(file_size, md5) self.request.sendall(mylib.s2b(res)) f = open(filename, 'rb') # 获取已经传输的文件大小 send_size = int(client_cmd[2]) # 定位文件的位置,用于断电续传 f.seek(send_size) # 判断文件是否传输完毕 while file_size != send_size: # 传输读取文件内容并传输,如果剩余大小每次传输的大小,则传输固定大小,如果剩余的大小 if file_size - send_size > conf.FILE_PER_SIZE: data = f.read(conf.FILE_PER_SIZE) send_size += conf.FILE_PER_SIZE else: data = f.read(file_size - send_size) send_size += (file_size - send_size) self.request.sendall(data) #print(file_size, send_size) else: res = "文件%s不存在" %filename self.request.sendall(mylib.s2b(res))
def checkspacesize(self, instructions): ''' 检查剩余空间是否可以上传文件方法 :param client_cmd: 用户命令 :return: 无 ''' # 获取剩余空间大小 import subprocess cmd_call = subprocess.Popen('du -s %s' %self.__home_path, shell = True, stdout = subprocess.PIPE) res = cmd_call.stdout.read() # 计算剩余空间,并返回 free_size = self.__current_user.get_quota() * 1024 * 1024 - int(mylib.b2s(res).split()[0]) self.request.send(mylib.s2b(r'{"freesize":%s}' %free_size))
def auth(self, user_input): ''' 认证方法 :param user_input: 用户输入命令 :return: ''' username = input('username: '******'password: '******'auth|%s|%s' % (username, mylib.jiami(password)))) # 调用服务端的认证方法,验证用户名密码 res = mylib.b2s(self.__sk.recv(100)) # 获取验证结果 print(res) if res == 'ok': # 如果验证成功,修改当前用户名和登录状态 self.__current_user = username self.__is_login = True
def cd(self, user_input): ''' 切换服务端目录方法 :param user_input: 用户指令 :return: 无 ''' if len(user_input) == 2: self.__sk.send(mylib.s2b('cd|{"path" : "%s"}' %user_input[1])) # 发送cd指令 res = json.loads(mylib.b2s(self.__sk.recv(200))) # 获取服务端反馈 if res['code'] == '500': self.__current_path = res['path'] # 修改当前目录等于返回来的目录 else: print(self.__code_list[res['code']]) else: print(self.__code_list['401'])
def get(self, instructions): ''' get 指令方法 :param instructions: 客户端命令 :return: 无 ''' import os import json res = json.loads(instructions[1]) filename = os.path.join(self.__current_path, res['filename']) # 获取文件名 if os.path.isfile(filename) and self.__check_path(filename): # 判断文件是否存在以及是否在家目录范围内 md5 = mylib.get_file_md5(filename) # 获取下载文件的md5 file_size = os.path.getsize(filename) # 获取下载文件的大小 self.request.send(mylib.s2b('ready|{"filesize":%s, "md5": "%s"}' %(file_size, md5))) # 通知客户端准备下载和MD5 f = open(filename, 'rb') send_size = res['sendsize'] # 获取已经下载的大小 f.seek(send_size) # 设定起始位置,用于续传 self.__loger.info('Begin send file %s to client [%s]' %(filename, self.client_address)) while file_size != send_size: # 传输读取文件内容并传输,如果剩余大小每次传输的大小,则传输固定大小,如果剩余的大小 if file_size - send_size > conf.FILE_PER_SIZE: data = f.read(conf.FILE_PER_SIZE) send_size += conf.FILE_PER_SIZE else: data = f.read(file_size - send_size) send_size += (file_size - send_size) try: self.request.send(data) except socket.error as e: self.__loger.error('%s when send file %s to client [%s]' %(e, filename, self.client_address)) break print(file_size, send_size) f.close() self.__loger.info('End send file %s to client [%s]' %(filename, self.client_address)) else: self.request.send(mylib.s2b('fail|303'))
def cd(self, user_input): ''' 切换服务端目录方法 :param user_input: 用户指令 :return: 无 ''' if len(user_input) == 2: self.__sk.send(mylib.s2b('cd|{"path" : "%s"}' % user_input[1])) # 发送cd指令 res = json.loads(mylib.b2s(self.__sk.recv(200))) # 获取服务端反馈 if res['code'] == '500': self.__current_path = res['path'] # 修改当前目录等于返回来的目录 else: print(self.__code_list[res['code']]) else: print(self.__code_list['401'])
def cd(self, instructions): ''' cd命令方法 :param instructions: 客户端命令 :return: 无 ''' import os import json path = json.loads(instructions[1])['path'] # 获取要cd的目录 tmp_path = os.path.abspath(os.path.join(self.__current_path, path)) # 定义临时目录 if os.path.isdir(tmp_path) and self.__check_path(tmp_path): #判断目录是否存在和是否绕过家目录 self.__current_path = tmp_path.replace('\\', '/') response_code = '500' else: response_code = '303' self.request.send(mylib.s2b('{"code":"%s", "path":"%s"}' %(response_code, self.__current_path.replace(self.__home_path, "")))) # 返回当前目录
def auth(self, user_input): ''' 认证方法 :param user_input: 用户输入命令 :return: ''' if len(user_input) ==1: username = input('username: '******'password: '******'auth|{"username":"******", "password":"******"}' % (username, mylib.jiami(password)))) # 调用服务端的认证方法,验证用户名密码 res = mylib.b2s(self.__sk.recv(200)) # 获取验证结果 print(self.__code_list[res]) if res == '200': # 如果验证成功,修改当前用户名和登录状态 self.__current_user = username self.__is_login = True else: print(self.__code_list['401'])
def auth(self, user_input): ''' 认证方法 :param user_input: 用户输入命令 :return: ''' if len(user_input) == 1: username = input('username: '******'password: '******'auth|{"username":"******", "password":"******"}' % (username, mylib.jiami(password)))) # 调用服务端的认证方法,验证用户名密码 res = mylib.b2s(self.__sk.recv(200)) # 获取验证结果 print(self.__code_list[res]) if res == '200': # 如果验证成功,修改当前用户名和登录状态 self.__current_user = username self.__is_login = True else: print(self.__code_list['401'])
def __runcmd(self, cmd): ''' 执行原生shell命令方法 :param cmd: shell命令 :return: 无 ''' self.__sk.sendall(mylib.s2b(cmd)) server_ack_msg = self.__sk.recv(100) cmd_res_msg = str(server_ack_msg.decode()).split("|") if cmd_res_msg[0] == "CMD_RESULT_SIZE": cmd_res_size = int(cmd_res_msg[1]) self.__sk.send(b"CLIENT_READY_TO_RECV") res = '' received_size = 0 while received_size < cmd_res_size: data = self.__sk.recv(500) received_size += len(data) res += str(data.decode()) else: print(str(res))