Example #1
0
    def re_put(self, select_file, file_put_unfinished_list):
        """
        断点续传
        :param select_file:
        :param file_put_unfinished_list:
        :return:
        """
        file_total_size = self.shelve_obj[select_file][1]
        uuid_file_name = self.shelve_obj[select_file][2]
        file_server_abs_path = self.shelve_obj[select_file][3]
        source_file_md5_value = self.shelve_obj[select_file][4]
        # 移除出去,在退出时不需要在服务端删除该文件了
        file_put_unfinished_list.remove(file_server_abs_path)
        self.send_certain_size_msg("re_put",
                                   file_total_size=file_total_size,
                                   uuid_file_name=uuid_file_name,
                                   file_server_abs_path=file_server_abs_path,
                                   source_file_md5_value=source_file_md5_value)
        response_data = self.get_response_from_server()
        print_info(response_data["response_msg"])

        f = open(select_file, "rb")

        finished_file_size = response_data["received_file_size"]
        f.seek(finished_file_size)
        # 发送文件中的数据到服务端
        self.send_data_from_file(f, finished_file_size, file_total_size)
        # 上传完成,删除断点续传的文件中的信息
        del self.shelve_obj[select_file]
Example #2
0
    def get(self, client_request_cmd, request_conn_obj):
        """
        从服务端下载文件
        :param client_request_cmd:
        :param request_conn_obj:
        :return:
        """
        current_thread_name = currentThread().name
        user_current_dir = self.user_info[current_thread_name]["user_current_dir"]
        # 客户端上传的相对路径get a/b/test.txt,相对路径与用户当前所在路径想拼
        file_relative_path = client_request_cmd["file_relative_path"]
        # 绝对路径
        file_abs_path = os.path.join(user_current_dir, file_relative_path)
        if os.path.exists(file_abs_path):
            file_total_size = os.path.getsize(file_abs_path)
            # 获取源文件的md5值
            file_md5_value = self.file_md5_value(file_abs_path)
            self.send_certain_size_response("200", request_conn_obj,
                                            file_total_size=file_total_size, file_md5_value=file_md5_value)
            f = open(file_abs_path, "rb")
            for line in f:
                request_conn_obj.send(line)
            f.close()
            print_info("file transfer successful!")

        else:
            print_info(self.STATUS_CODE["201"])
            self.send_certain_size_response("201", request_conn_obj)
Example #3
0
    def create_user(self, client_request_cmd, request_conn_obj):
        """
        创建新用户,验证用户是否存在,同时在home目录下创建文件夹
        :param client_request_cmd:
        :param request_conn_obj:
        :return:
        """

        new_user_name = client_request_cmd["new_user_name"]
        new_user_password = client_request_cmd["new_user_password"]
        # 用户输入的是G,保存到文件中是B,字节,便于后面比较大小
        # 要转换为str才能保存到ini文件中,由于用户可能输入小数,所以用float
        user_quota = str(float(client_request_cmd["user_quota"].replace("G", ""))*1024*1024*1024)
        # 保存字节到文件中
        # 加密后的密码
        new_user_password = self.hash_password(new_user_password)
        # 新加的用户,在用户家目录下创建目录
        new_user_home_dir = os.path.join(settings.USER_HOME_DIR, new_user_name)
        if self.accounts.has_section(new_user_name):
            print_info(self.STATUS_CODE["501"])
            self.send_certain_size_response("501", request_conn_obj)
        else:
            self.accounts.add_section(new_user_name)
            self.accounts.set(new_user_name, "password", new_user_password)
            self.accounts.set(new_user_name, "quota", user_quota)
            self.accounts.set(new_user_name, "left_quota", user_quota)
            self.accounts.write((open(settings.ACCOUNT_FILE, "w")))
            self.send_certain_size_response("500", request_conn_obj)
            # 创建用户家目录
            os.mkdir(new_user_home_dir)
            print_info(self.STATUS_CODE["500"])
Example #4
0
 def __print_help_msg():
     """
     打印启动的帮助信息,只是内部使用,不对外使用,可以设置为隐藏函数
     :return:
     """
     help_msg = """
     [python run_server.py start] to start 7.ftp server!
     [python run_server.py stop] to stop 7.ftp server!
     """
     print_info(help_msg)
Example #5
0
 def verify_file_md5(self, source_file_md5_value,
                     finally_file_storage_path):
     """
     验证文件的md5
     :param source_file_md5_value:
     :param finally_file_storage_path:
     :return:
     """
     file_md5_value = self.file_md5_value(finally_file_storage_path)
     if source_file_md5_value == file_md5_value:
         print_info("\n file is same with sever,file download successful!")
     else:
         print_info("\n file is not same with server!", "error")
Example #6
0
 def verify_md5(self, source_file_md5, file_abs_path):
     """
     用于验证接受的文件,与客户端的文件的md5是否相同
     :param source_file_md5:
     :param file_abs_path:
     :return:
     """
     file_md5_value = self.file_md5_value(file_abs_path)
     # 验证文件是否和客户端一样
     if file_md5_value == source_file_md5:
         print_info("file is same with client,file received done")
     else:
         print_info("file is not same with client!", "error")
Example #7
0
    def quit(self, client_cmd_list):
        """
        退出客户端,用户只能输入quit,所以len(cmd_list)==0
        :return:
        """

        if self.verify_client_cmd_list(client_cmd_list, 0):
            self.send_certain_size_msg("quit")
            print_info("%s waiting for you come again! bye bye!" %
                       self.username)
            exit()
        else:
            print_info("your input is illegal!you can just input [quit]!",
                       "error")
Example #8
0
    def put(self, client_cmd_list):
        """
        这里就只允许用户上传所在系统的任意文件,但是需要写出绝对路径
        :param client_cmd_list:
        :return:
        """
        if self.verify_client_cmd_list(client_cmd_list, 1):
            file_abs_path = client_cmd_list[0]

            if os.path.isfile(file_abs_path):
                file_total_size = os.path.getsize(file_abs_path)
                # 先把文件的信息发送到服务端,然后在发送文件的内容
                if self.left_quota > file_total_size:
                    # 获取md5值,用于验证数据的准确性
                    file_md5_value = self.file_md5_value(file_abs_path)
                    file_name = os.path.basename(file_abs_path)
                    # 把文件名发送到服务端,服务端验证文件是否已经存在,如果已经存在,就重命名为uuid-filename
                    self.send_certain_size_msg("put",
                                               file_total_size=file_total_size,
                                               file_name=file_name,
                                               file_md5_value=file_md5_value)
                    # 获取服务端发送的结果
                    response_data = self.get_response_from_server()
                    print_info(response_data["response_msg"])
                    # 如果上传的文件已经存在,服务端会把文件重命名为uuid-file_name,这时只能从服务端获取到该文件名
                    # 用于断点续传使用

                    uuid_file_name = response_data["file_name"]
                    # 文件在服务端的绝对路径
                    file_server_abs_path = response_data["file_abs_path"]
                    self.shelve_obj[file_abs_path] = [
                        "put_unfinished", file_total_size, uuid_file_name,
                        file_server_abs_path, file_md5_value
                    ]
                    # 用于断点续传的信息存储
                    f = open(file_abs_path, "rb")
                    finished_file_size = 0
                    self.send_data_from_file(f, finished_file_size,
                                             file_total_size)
                    # 上传完成,删除断点续传的文件中的信息
                    del self.shelve_obj[file_abs_path]

                    print_info("\nfile transfer finished!")
                else:
                    print_info("left quota is not enough!")
            else:
                print_info("your put file is not a file!")
        else:
            print_info("your input is illegal!for example [put e:\\file.txt]")
Example #9
0
 def login(self):
     """
     用户登录方法
     :return:
     """
     if self.auth():
         self.unfinished_file_deal()
         while True:
             # 用户输入ls, get file ,put file,cd dir
             print_info("you can input [quit] to exit client!")
             client_cmd = input("your input %s#" %
                                self.terminal_display).strip()
             if not client_cmd:
                 continue
             client_cmd_list = client_cmd.split()
             # 用户输入的第一个命令
             if hasattr(self, client_cmd_list[0]):
                 func = getattr(self, client_cmd_list[0])
                 # 把后面的内容传给方法
                 func(client_cmd_list[1:])
Example #10
0
    def re_get(self, client_request_cmd, request_conn_obj):
        """
        重新获取没有获取完成的数据
        :param client_request_cmd:
        :param request_conn_obj:
        :return:
        """
        response_data = client_request_cmd
        file_abs_path = response_data["file_abs_path"]
        file_total_size = response_data["file_total_size"]
        if os.path.exists(file_abs_path):
            if os.path.getsize(file_abs_path) == file_total_size:
                self.send_certain_size_response("600", request_conn_obj)
                received_file_size = response_data["received_file_size"]
                f = open(file_abs_path, "rb")
                f.seek(received_file_size)
                for line in f:
                    request_conn_obj.send(line)
                f.close()
                print_info("%s file re_get success" % file_abs_path)
            else:
                # source file changed,you can not re_get
                print_info(self.STATUS_CODE["602"])
                self.send_certain_size_response("602", request_conn_obj)

        else:
            # re_get file not exist
            print_info(self.STATUS_CODE["601"])
            self.send_certain_size_response("601", request_conn_obj)
Example #11
0
    def create_user(self):
        """
        新建用户,同时在服务端Home目录下创建家目录,并设置用户磁盘空间大小
        :return:
        """
        exit_flag = True
        while exit_flag:
            new_user_name = input("please input new user name:").strip()
            new_user_password = input("please set user password:"******"please set user quota[G]:").strip()
            # 验证用户的输入是否标准
            # 其中用户配额,由于单位过多,所以这里只能存G,服务端会进行转换为字节
            # 这里会验证用户配额输入的否标准
            if new_user_name and new_user_password and user_quota.endswith("G") \
                    and user_quota.replace("G", "").replace(".", "").isdigit():
                self.send_certain_size_msg("create_user",
                                           new_user_name=new_user_name,
                                           new_user_password=new_user_password,
                                           user_quota=user_quota)
                response_data = self.get_response_from_server()
                if response_data["response_code"] == "500":
                    print_info(response_data["response_msg"])
                    exit_flag = False
                else:
                    print_info(response_data["response_msg"])
                    exit_flag = False

            else:
                print_info("your input is illegal!")
                exit_flag = False
Example #12
0
 def auth(self):
     """
     用户登录方法,首先是用户登录,登录成功后才能进行后面的操作
     :return:
     """
     count = 0
     while count < 3:
         username = input("please input username:"******"please input password:"******"auth",
                                        username=username,
                                        password=password)
             response_data = self.get_response_from_server()
             if response_data["response_code"] == "100":
                 print_info(response_data["response_msg"])
                 self.terminal_display = "[%s]" % username
                 self.username = username
                 self.left_quota = response_data["left_quota"]
                 # 用于断点续传处的路径拼接
                 self.user_current_dir = response_data["user_current_dir"]
                 return True
             else:
                 print_info(response_data["response_msg"], "error")
                 count += 1
         else:
             print_info("username or password an not be null!", "error")
             count += 1
     return False
Example #13
0
    def cd(self, client_cmd_list):
        """
        cd a/b 由于用户只能在自己的家目录下下切换,所以会把用户输入的目录与服务端的user_current_dir拼
        :param client_cmd_list:
        :return:
        """
        if self.verify_client_cmd_list(client_cmd_list, 1):
            target_path = client_cmd_list[0]
            self.send_certain_size_msg("cd", target_path=target_path)
            response_data = self.get_response_from_server()
            if response_data["response_code"] == "400":
                client_terminal_display_dir = response_data[
                    "client_terminal_display_dir"]
                if len(client_terminal_display_dir) == 0:
                    self.terminal_display = "[%s]" % self.username

                else:
                    self.terminal_display = "[%s]" % client_terminal_display_dir
                # 记录用户的当前路径,用于断点续传时,获取文件使用
                self.user_current_dir = response_data["user_current_dir"]
                print_info("change dir success!")
            else:
                print_info(response_data["response_msg"])
        else:
            print_info("your input is illegal!for example [cd a/b ]")
Example #14
0
    def ls(self, client_cmd_list):
        """
        列出用户当前目录下的内容,当前目录是以服务端的self.user_current_dir为准
        :param client_cmd_list:
        :return:
        """
        if self.verify_client_cmd_list(client_cmd_list, 0):
            self.send_certain_size_msg("ls")
            response_data = self.get_response_from_server()
            if response_data["response_code"] == "300":
                print_info(response_data["response_msg"])
                cmd_result_total_size = response_data["cmd_result_total_size"]
                received_file_size = 0

                while received_file_size < cmd_result_total_size:
                    left_file_size = cmd_result_total_size - received_file_size
                    if left_file_size < self.MSG_SIZE:
                        data = self.client_socket_obj.recv(left_file_size)
                        # 这样操作是不可以的len(data)!=left_file_size
                        # received_file_size += left_file_size
                    else:
                        data = self.client_socket_obj.recv(self.MSG_SIZE)
                        # received_file_size += self.MSG_SIZE
                    received_file_size += len(data)
                    print_info(data.decode("gbk"))
        else:
            print_info("your input is illegal!for example [ls ]")
Example #15
0
 def send_certain_size_msg(self, action_type, **kwargs):
     """
     发送固定打下的包到服务端,这是处理粘包问题的必备思路
     首先发送一个固定大小的包到对方,对方会按照指定大小接受,如果是文件,数据包中会含有要发送的文件的大小
     后面再发送文件或其他内容,对方只需要知道文件的大小,通过循环,即可接受全部的内容
     :param action_type:
     :param kwargs:
     :return:
     """
     msg_data = {"action_type": action_type, "fill": ""}
     # 更新msg_data字典,因为可能会加入新的key,value放入到了kwargs中
     msg_data.update(kwargs)
     bytes_msg_data = json.dumps(msg_data).encode("utf-8")
     # 为了避免粘包问题,每次首先都发送一个定长的数据(这里定长为1024字节,足够使用了)到服务端,
     # 服务端根据这个数据中的信息进行后面的操作
     if len(bytes_msg_data) < self.MSG_SIZE:
         # 进行数据填充,使得长度为1024字节
         msg_data["fill"] = msg_data["fill"].zfill(self.MSG_SIZE -
                                                   len(bytes_msg_data))
         bytes_msg_data = json.dumps(msg_data).encode("utf-8")
     self.client_socket_obj.send(bytes_msg_data)
     print_info("your commands has send to 7.ftp server successful!")
Example #16
0
    def cd(self, client_request_cmd, request_conn_obj):
        """
        切换目录
        :param client_request_cmd:
        :param request_conn_obj:
        :return:
        """
        current_thread_name = currentThread().name
        user_current_dir = self.user_info[current_thread_name]["user_current_dir"]
        user_home_dir = self.user_info[current_thread_name]["user_home_dir"]
        print("------", self.user_info)

        target_path = client_request_cmd["target_path"]
        # E:\PythonProject\python-test\homework\7.ftp\server\home\vita\test\..\..使用abspath能去掉..
        # 变为E:\PythonProject\python-test\homework\7.ftp\server\home\vita\test

        target_abs_path = os.path.abspath(os.path.join(user_current_dir, target_path))
        print_info(target_abs_path)
        if os.path.isdir(target_abs_path):
            if target_abs_path.startswith(user_home_dir):
                client_terminal_display_dir = target_abs_path.replace(user_home_dir, "")

                print_info(self.STATUS_CODE["400"])
                user_current_dir = target_abs_path
                self.user_info[current_thread_name]["user_current_dir"] = target_abs_path
                self.send_certain_size_response("400",
                                                request_conn_obj,
                                                client_terminal_display_dir=client_terminal_display_dir,
                                                user_current_dir=user_current_dir)
                print_info("dir change success!")
            else:
                # 输出无权限
                self.send_certain_size_response("402", request_conn_obj)
                print_info(self.STATUS_CODE["402"])
        else:
            # 输出目录不存在
            self.send_certain_size_response("401", request_conn_obj)
            print_info(self.STATUS_CODE["401"])
Example #17
0
 def interactive(self):
     """
     与用户交互的方法
     :return:
     """
     exit_flag = True
     while exit_flag:
         info = """
         1.创建用户
         2.登录
         3.退出
         """
         choice_list = {"1": "create_user", "2": "1.login", "3": "quit"}
         print_info(info)
         your_choice = input("please input your choice:").strip()
         if your_choice in choice_list:
             if choice_list[your_choice] == "quit":
                 self.quit([])
             else:
                 func = getattr(self, choice_list[your_choice])
                 func()
         else:
             print_info("your input is illegal")
Example #18
0
    def keep_running(self):
        """
        这里是允许多用户登录,但这里没有使用多线程,是通过while True的方式,
        一个用户断开连接,另一个用户才能继续连接
        :return:
        """
        self.server_socket_obj.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_socket_obj.bind((settings.FTP_SERVER_HOST, settings.FTP_SERVER_PORT))
        self.server_socket_obj.listen(5)
        while True:
            print("waiting client to connect!")
            request_conn_obj, client_addr = self.server_socket_obj.accept()
            # self.client_addr是个元组('127.0.0.1','13850')
            print_info("client connect:ip:%s port:%s" % (client_addr[0], client_addr[1]))
            try:
                t = self.pool.get_thread()  # 每次创建都从队列中拿取一个线程对象
                obj = t(target=self.handle_client_request, args=(request_conn_obj,))  # 使用线程对象创建线程
                obj.start()  # 启动线程
                # self.handle_client_request(request_conn_obj)
                # 客户端输入quit退出程序时,服务端的
            except Exception as e:
                print(e)

            print_info("client closed connection!ip:%s port:%s" % (client_addr[0], client_addr[1]))
Example #19
0
    def get(self, client_cmd_list):
        """
        从服务端下载文件,保存到客户端的file_storage路径下,包含md5验证
        :param client_cmd_list:
        :return:
        """
        if self.verify_client_cmd_list(client_cmd_list, 1):
            # get a/b/test.txt会从服务端的当前所在路径下的a/b/中获取test.txt
            file_relative_path = client_cmd_list[0]
            file_name = os.path.basename(file_relative_path)
            self.send_certain_size_msg("get",
                                       file_relative_path=file_relative_path)

            response_data = self.get_response_from_server()
            if response_data["response_code"] == "200":
                # 判断要下载的文件在本地下载路径中是否存在,如果已经存在,就重命名
                if os.path.exists(
                        os.path.join(settings.FILE_STORAGE_PATH, file_name)):
                    # print("ewe-wew".split("-")[1])这样就可获取到原文件名,便于后面操作,
                    # 因为重名后,只有客户端有这文件
                    file_name = "%s-%s" % (uuid.uuid1(), file_name)
                # 存放文件的路径,放在storage下,先存为.download,用于断点续传
                file_storage_path_download = os.path.join(
                    settings.FILE_STORAGE_PATH, "%s.download" % file_name)
                print_info(response_data["response_msg"])
                file_total_size = response_data["file_total_size"]
                source_file_md5_value = response_data["file_md5_value"]
                # 准备开始写入文件
                f = open(file_storage_path_download, "wb")
                # 把下载的文件信息保存到shelve文件中,供断点续传的信息记录
                source_server_file_abs_path = os.path.join(
                    self.user_current_dir, file_relative_path)
                self.shelve_obj[source_server_file_abs_path] = [
                    "get_unfinished", file_total_size,
                    "%s.download" % file_name, source_file_md5_value
                ]
                # 用于断点续传信息记录完成
                received_file_size = 0
                self.write_data_from_receive(f, received_file_size,
                                             file_total_size)

                # 文件下载成功,重命名文件
                finally_file_storage_path = os.path.join(
                    settings.FILE_STORAGE_PATH, file_name)
                os.rename(file_storage_path_download,
                          finally_file_storage_path)
                del self.shelve_obj[source_server_file_abs_path]
                # 文件下载成功,把用于断点续传消息记录的该文件消息删除
                self.verify_file_md5(source_file_md5_value,
                                     finally_file_storage_path)
            else:
                print_info(response_data["response_msg"])
        else:
            print_info("your input is illegal!for example [get file.txt]")
Example #20
0
    def auth(self, client_request_cmd, request_conn_obj):
        """
        用户登录验证
        :param client_request_cmd:
        :param request_conn_obj:
        :return:
        """
        current_thread_name = currentThread().name
        username = client_request_cmd["username"]
        password = client_request_cmd["password"]

        # 加密后的密码
        password = self.hash_password(password)
        if username in self.accounts:
            real_password = self.accounts[username]["password"]
            if password == real_password:
                user_current_dir = os.path.join(settings.USER_HOME_DIR, username)
                user_home_dir = os.path.join(settings.USER_HOME_DIR, username)
                username = username
                # 返回给客户端,用于记录当前用户的磁盘配额,每次put,
                # 客户端直接从自己记录的配额中减去,
                # 验证时也直接使用自己的配额记录,就不需要再次从服务端获取了
                # 服务端也会进行减法
                left_quota = float(self.accounts[username]["left_quota"])

                self.user_info[current_thread_name] = {}
                self.user_info[current_thread_name]["user_current_dir"] = user_current_dir
                self.user_info[current_thread_name]["user_home_dir"] = user_home_dir
                self.user_info[current_thread_name]["username"] = username
                self.user_info[current_thread_name]["left_quota"] = left_quota

                self.send_certain_size_response("100", request_conn_obj, left_quota=left_quota,
                                                user_current_dir=user_current_dir)
                print_info(self.STATUS_CODE["100"])

            else:
                print_info("your password is not correct", "error")
                self.send_certain_size_response("101", request_conn_obj)
        else:
            print_info("user %s not exist" % username, "error")
            self.send_certain_size_response("102", request_conn_obj)
Example #21
0
    def unfinished_file_deal(self):
        """
        断点续传处理
        :return:
        """
        out_exit_flag = True
        while out_exit_flag:
            # 如果没有断点的文件,直接退出

            if len(list(self.shelve_obj.keys())) == 0:
                break
            # 如果有没有上传成功的文件,同时用户不想处理,就自动在服务端把改文件删除,因为是无用文件,
            # 同时也是为了用户磁盘配额的准确性,因为在程序突然中断,包含服务端和客户端,还没有把剩余的配额写入文件中
            file_put_unfinished_list = []
            for index, file_abs_path in enumerate(self.shelve_obj.keys()):
                #  self.shelve_obj[source_server_file_abs_path] = ["get_unfinished",
                #                                                                 file_total_size,
                #                                                                 "%s.download" % file_name]
                info = self.shelve_obj[file_abs_path][0]
                file_total_size = self.shelve_obj[file_abs_path][1]
                file_name = self.shelve_obj[file_abs_path][2]
                if info == "get_unfinished":
                    received_file_size = os.path.getsize(
                        os.path.join(settings.FILE_STORAGE_PATH, file_name))
                    received_percent = received_file_size / file_total_size * 100
                    print(index, info, file_name,
                          "received_file_size:%s " % received_file_size,
                          "file_total_size:%s" % file_total_size,
                          "received_percent[百分比]:%s" % received_percent)
                elif info == "put_unfinished":
                    # self.shelve_obj[file_abs_path] = ["put_unfinished", file_total_size,
                    #                                   uuid_file_name, file_server_abs_path]
                    # 加到列表中,用于后面的处理
                    file_put_unfinished_list.append(
                        self.shelve_obj[file_abs_path][3])
                    print(index, info, file_name)
            exit_flag = True
            while exit_flag:
                your_choice = input(
                    "you can input [quit] to finish deal unfinished file!"
                    "please input your choice:").strip()
                if your_choice == "quit":
                    # 如果有没有上传成功的,就删除服务端已经上传的部分,无用的文件就删除掉吧
                    if len(file_put_unfinished_list) != 0:
                        self.send_certain_size_msg(
                            "del_unfinished_put",
                            file_put_unfinished_list=file_put_unfinished_list)
                        response_data = self.get_response_from_server()
                        print_info(response_data["response_msg"])
                    # 用户选择不处理,就删除文件中的内容,不能每次登录都打扰用户
                    for index, file_abs_path in enumerate(
                            self.shelve_obj.keys()):
                        del self.shelve_obj[file_abs_path]
                    out_exit_flag = False
                    break

                keys_list = list(self.shelve_obj.keys())
                if your_choice.isdigit(
                ) and int(your_choice) <= len(keys_list):
                    your_choice = int(your_choice)
                    select_file = keys_list[your_choice]
                    # self.shelve_obj[source_server_file_abs_path] = ["get_unfinished",
                    #                                                                 file_total_size,
                    #                                                                 "%s.download" % file_name,
                    #                                                                 source_file_md5_value]
                    if self.shelve_obj[select_file][0] == "get_unfinished":
                        file_total_size = self.shelve_obj[select_file][1]
                        file_name = self.shelve_obj[select_file][2]
                        source_file_md5_value = self.shelve_obj[select_file][3]
                        file_storage_path = os.path.join(
                            settings.FILE_STORAGE_PATH, file_name)
                        received_file_size = os.path.getsize(file_storage_path)
                        self.send_certain_size_msg(
                            "re_get",
                            file_abs_path=select_file,
                            file_total_size=file_total_size,
                            file_name=file_name,
                            received_file_size=received_file_size)
                        response_data = self.get_response_from_server()
                        if response_data["response_code"] == "600":
                            f = open(file_storage_path, "ab")
                            self.write_data_from_receive(
                                f, received_file_size, file_total_size)
                            finally_file_storage_path = file_storage_path.replace(
                                ".download", "")
                            os.rename(file_storage_path,
                                      finally_file_storage_path)
                            # 重新获取文件,验证md5
                            self.verify_file_md5(source_file_md5_value,
                                                 finally_file_storage_path)
                            del self.shelve_obj[select_file]
                            # out_exit_flag = False
                            break

                        else:
                            print_info(response_data["response_msg"])
                            exit_flag = False
                    # self.shelve_obj[file_abs_path] = ["put_unfinished", file_total_size,
                    # uuid_file_name, file_server_abs_path, file_md5_value]
                    elif self.shelve_obj[select_file][0] == "put_unfinished":
                        # 继续未完成的继续上传
                        self.re_put(select_file, file_put_unfinished_list)

                        print_info("\nfile re_put transfer finished!")
                        break
                else:
                    # 输入不是数字,提示输入时不合法的。
                    print("your input is illegal!")