Пример #1
0
    def ls(self,*args):
        """
        显示客户端的文件列表详细信息
        :param args:
        :return: 返回文件列表
        """
        try:
            # 发送命令到服务端
            self.client.send(bytes("ls|", encoding='utf-8'))
            # 接收服务端发送结果的大小
            total_data_len = self.client.recv(1024).decode()
            # 收到了并发送一个ready标识给服务端
            self.client.send(bytes("ready", 'utf-8'))

            # 开始接收数据
            total_size = int(total_data_len)  # 文件总大小
            has_recv = 0  # 已经接收的文件大小
            exec_result = bytes("", 'utf8')
            while True:
                # 如果文件总大小等于已经接收的文件大小,则退出
                if total_size == has_recv:
                    break
                data = self.client.recv(1024)
                has_recv += len(data)
                exec_result += data
            # 获取结果中文件及文件夹的数量
            return_result = str(exec_result, 'utf-8')
            file_count = int(return_result.split("|")[0])
            if file_count == 0:
                return_result = "目前无上传记录"
            else:
                return_result = return_result.split("|")[1]
            common.message(return_result,"INFO")
        except Exception as e:
            logger.error("client ls:{0}".format(e))
Пример #2
0
    def delete(self,command):
        """
        删除目录或文件名
        :param command: delete|PycharmProjects/untitled/project/FTPv1/FTPServer/upload/admin/test/aa
        :return:
        """
        # 发送命令消息给服务端
        self.client.sendall(bytes(command, encoding='utf-8'))
        # 接收服务端发来的回应消息
        del_msg = str(self.client.recv(1024), encoding='utf-8')
        reve_status = int(del_msg.split("|")[0])
        reve_delfilename_fsize = int(del_msg.split("|")[1])

        if del_msg == code.FOLDER_DEL_SUCC:
            common.message(">>>>>>>删除目录成功","INFO")
        elif reve_status == code.FILE_DEL_SUCC:
            #更新用户空间配额大小
            self.userspace -= reve_delfilename_fsize
            common.message(">>>>>>>删除文件名成功","INFO")
        elif reve_status == code.FILE_DEL_FAIL:
            common.message(">>>>>>>删除目录或文件名失败","ERROR")
        elif reve_status == code.FILE_DEL_EMPTY:
            common.message(">>>>>>>当前目录下不是空目录,无法删除!","ERROR")
        else:
            common.message(">>>>>>>命令行请输入需要删除的路径目录或文件名!","ERROR")
Пример #3
0
    def get(self,command):
        """
        下载文件
        :param command:
        :return:
        """
        return_result = ""
        # 发送基本信息到服务端 (command,username,file)
        self.client.send(bytes(command, encoding='utf-8'))
        # 先接收到命令是否正确标识,1 文件存在, 0 文件不存在
        ack_by_server = self.client.recv(1024)
        try:
            # 文件名错误,当前路径下找不到
            if str(ack_by_server, encoding='utf-8') == "0":
                return_result = "\n当前目录下未找到指定的文件,请到存在目录下执行get操作!"
            else:
                # 给服务端回应收到,防止粘包
                self.client.send(bytes("ok", 'utf8'))

                # 文件存在,开始接收文件基本信息(大小,文件名)
                file_info = self.client.recv(1024).decode()
                file_size = int(file_info.split("|")[0])
                file_name = file_info.split("|")[1]
                file_md5 = file_info.split("|")[2]

                # 2 发送 ready 标识,准备开始接收文件
                self.client.send(bytes("ready", 'utf8'))

                # 3 开始接收数据了
                has_recv = 0
                with open(os.path.join(settings.DOWNLOAD_FILE_PATH, file_name), 'wb') as f:
                    while True:
                        # 如果文件总大小等于已经接收的文件大小,则退出
                        if file_size == has_recv:
                            break
                        data = self.client.recv(1024)
                        f.write(data)
                        has_recv += len(data)
                        # 打印下载进度条
                        common.progress_bar(has_recv, file_size)
                return_result = "\n文件下载成功"
                logger.info("download file<{0}> from server successful".format(file_name))
                # md5文件验证
                check_md5 = common.md5sum(os.path.join(settings.DOWNLOAD_FILE_PATH, file_name))
                if check_md5 == file_md5:
                    logger.info("md5 check for file<{0}> succ!".format(file_name))
                    return_result += ", MD5 验证成功! "
                else:
                    return_result += ", MD5 验证文件不匹配! "
            common.message(return_result,"INFO")
        except Exception as e:
            logger.error(e)
Пример #4
0
 def cd(self,command):
     """
     切换目录路径
     :param command: cd|.. 或cd|foldername
     :return: 返回状态信息
     """
     # 发送命令消息给服务端
     self.client.sendall(bytes(command, encoding='utf-8'))
     # 接收服务端发来的回应消息
     cd_msg = str(self.client.recv(1024), encoding='utf-8')
     result_status,result_folder = cd_msg.split("|")
     if result_status == "0":
         result_value = "当前是根目录"
     elif result_status == "1":
         result_value = "目录已切换到:{0}".format(result_folder)
     elif result_status == "2":
         result_value = "切换失败, {0} 不是一个目录".format(result_folder)
     elif result_status == "3":
         result_value = "命令无效:{0}".format(result_folder)
     common.message(result_value,"INFO")
Пример #5
0
 def mk(self,command):
     """
     创建目录
     :param command: 发送命令消息格式;mk|test或mk|/test/yj
     :return:
     """
     #发送命令消息给服务端
     self.client.sendall(bytes(command,encoding='utf-8'))
     #接收服务端发来的回应消息
     mk_msg = str(self.client.recv(1024), encoding='utf-8')
     mk_msg = int(mk_msg)
     if mk_msg == code.FILE_MK_SUCC:
         common.message(">>>>>>>创建目录成功","INFO")
     elif mk_msg == code.FILE_MK_FAIL:
         common.message(">>>>>>>创建目录失败","ERROR")
     else:
         common.message(">>>>>>>请输入文件夹名","ERROR")
Пример #6
0
 def login(self):
     while True:
         username = str(input("请输入用户名:")).strip()
         password = str(input("请输入密码:")).strip()
         #对密码进行md5加密
         password = common.md5(password)
         #登录认证
         auth_status = self.check_auth(username,password)
         if auth_status == code.AUTH_SUCC:
             common.message(">>>>>>>登录成功","INFO")
             return True
         elif auth_status == code.AUTH_USER_ERROR:
             common.message(">>>>>>>用户名不存在","ERROR")
             return False
         else:
             common.message(">>>>>>>用户名或密码错误!","ERROR")
             return False
Пример #7
0
def run():
    common.message(template.START_MENU, "INFO")
    common.message(
        "正在连接服务器 {0}:{1}......".format(settings.FTP_SERVER_IP,
                                       settings.FTP_SERVER_PORT), "INFO")

    #创建对象
    client_obj = client(settings.FTP_SERVER_IP, settings.FTP_SERVER_PORT)
    #连接服务器,返回结果
    conn_result = client_obj.connect()
    if conn_result == code.CONN_SUCC:
        common.message("连接成功!", "INFO")
        #客户端登录
        login_result = client_obj.login()
        if login_result:
            exit_flag = False
            while not exit_flag:
                show_menu = template.LOGINED_MENU.format(
                    client_obj.username,
                    str(int(client_obj.totalspace / 1024 / 1024)),
                    str(int(client_obj.userspace / 1024 / 1024)))
                common.message(show_menu, "INFO")
                inp_command = common.input_command("[请输入命令]:")
                if inp_command == "quit":
                    exit_flag = True
                else:
                    #获取命令
                    func = inp_command.split("|")[0]
                    try:
                        if hasattr(client, func):
                            #从模块寻找到函数
                            target_func = getattr(client, func)
                            #执行函数
                            target_func(client_obj, inp_command)
                        else:
                            common.message(
                                "Client {0} 未找到".format(inp_command), "ERROR")
                    except Exception as e:
                        logger.error(e)
    else:
        common.message("连接失败!", "ERROR")
Пример #8
0
    def put(self,command):
        """
        上传文件
        :param command: put|folderfile
        :return:
        """
        file_name = command.split("|")[1]
        if os.path.isfile(file_name):
            filename = os.path.basename(file_name)
            fsize = os.stat(file_name).st_size
            fmd5 = common.md5sum(file_name)

            # 将基本信息发给服务端
            file_msg = "{cmd}|{file}|{filesize}|{filemd5}".format(cmd='put',
                                                                  file=filename,
                                                                  filesize=fsize,
                                                                  filemd5=fmd5)
            self.client.send(bytes(file_msg, encoding='utf8'))
            logger.info("send file info: {0}".format(file_msg))
            #接收来自服务端数据
            put_msg = str(self.client.recv(1024),encoding='utf-8')
            try:
                #正常上传文件
                if put_msg == "ok":
                    #判断是否超过用户空间配额
                    if self.userspace + fsize > self.totalspace:
                        common.message("用户磁盘空间不足,无法上传文件,请联系管理员!","ERROR")
                    else:
                        self.userspace += fsize
                        new_size = 0
                        with open(file_name,'rb') as f:
                            for line in f:
                                self.client.sendall(line)
                                new_size += len(line)
                                # 打印上传进度条
                                common.progress_bar(new_size,fsize)
                                if new_size >= fsize:
                                    break
                #断点续传文件
                if put_msg.split("|")[0] == "continue":
                    send_size = int(put_msg.split("|")[1])
                    common.message("服务端存在此文件,但未上传完,开始断点续传......","INFO")
                    new_size = 0
                    with open(file_name,'rb') as f:
                        #用seek来进行文件指针的偏移,实现断点续传的功能
                        f.seek(send_size)
                        while fsize - send_size > 1024:
                            revedata = f.read(1024)
                            self.client.sendall(revedata)
                            new_size += len(revedata)
                            #打印上传进度条
                            common.progress_bar(new_size, fsize)
                        else:
                            revedata = f.read(fsize - send_size)
                            self.client.sendall(revedata)
                            # 打印上传进度条
                            common.progress_bar(new_size, fsize)

                #不存在断点文件情况,询问是否覆盖掉原文件
                if put_msg == "full":
                    inp_msg = common.message("服务端存在完整文件,是否覆盖掉原文件[输入y或n]:","INFO")
                    inp = str(input(inp_msg)).strip().lower()
                    if inp == "y":
                        with open(file_name, 'rb') as f:
                            new_size = 0
                            for line in f:
                                self.client.sendall(line)
                                new_size += len(line)
                                #打印上传进度条
                                common.progress_bar(new_size, fsize)
                                if new_size >= fsize:
                                    break
                    elif inp == "n":
                        sys.exit()
                    else:
                       common.message("无效命令", "ERROR")
                logger.info("upload file<{0}> successful".format(file_name))
                common.message("文件上传成功", "INFO")
            except Exception as e:
                logger.error("文件上传失败:{0}".format(e))
                common.message("文件上传失败!", "ERROR")
        else:
            common.message("文件不存在!", "ERROR")