zoukankan      html  css  js  c++  java
  • python_网络编程之端点续传

    这个例子分为服务端和客户端,都做了大量的注释,很容易读懂

    服务端

    ##以下代码是梳理思路
    # import socketserver
    # import os  #使用os模块的join方法
    # import json
    # cod={'1001':'开始上传','1002':'开始续传'}
    # class Nbserver(socketserver.BaseRequestHandler):
    #     def handle(self):
    #         while 1:
    #             # 1 , 接受命令
    #             upload_cmd_bytes=self.request.recv(2048) #最大是8k
    #             # upload_cmd_str=json.loads(upload_cmd_bytes).decode("utf8")  #错误的写法
    #             cmd_dic = json.loads(upload_cmd_bytes.decode("utf8"))  #是字节有解码的方法
    #
    #
    #             # 2,获取文件信息
    #             file_md5=cmd_dic['md5']
    #             home=r'E:老男孩课程mysql_db'
    #             file_mdf_path=os.path.join(home,'zhangzijie',file_md5)
    #
    #             exist=os.path.exists(file_mdf_path)
    #             if not exist: #不续传
    #                 #我没有这个文件,你开始给我传
    #                 #设计状态码
    #                 response = {'code': 1001}
    #                 self.request.sendall(b'1001')
    #             else:
    #                 #怎么续传呢?你的告诉客户端我已经有多少了,你已经给我传了多少了,对方才能
    #                 #从断开的那里进行继续传
    #                 #根据文件路径获取大小
    #                 exist_szie=os.stat(file_mdf_path).st_size
    #                 #定义一个协议
    #                 response={'code':1002,'size':exist_szie}
    #                 self.request.sendall(json.dumps(response).encode("utf-8"))
    #                 self.request.sendall(b'1002')
    #
    #
    #             # print(cmd_dic)
    #
    #
    # server=socketserver.ThreadingTCPServer(('127.0.0.1',8001),Nbserver)
    # server.serve_forever()
    
    ###########################################################################################
    # 下面这个例子可以运行,就是上传的目录64行的zhangzijie需要指定
    # 开始编写上传部分
    # import socketserver
    # import os  #使用os模块的join方法
    # import json
    # cod={'1001':'开始上传','1002':'开始续传'}
    # class Nbserver(socketserver.BaseRequestHandler):
    #     def handle(self):
    #         while 1:
    #             # 1 , 接受命令
    #             upload_cmd_bytes=self.request.recv(2048) #最大是8k
    #             # upload_cmd_str=json.loads(upload_cmd_bytes).decode("utf8")  #错误的写法
    #             cmd_dic = json.loads(upload_cmd_bytes.decode("utf8"))  #是字节有解码的方法《########
    #                                                                                               #
    #                                                                                               #
    #             # 2,获取文件信息                                                                   #
    #             file_md5=cmd_dic['md5']  #
    #             file_name=cmd_dic['file_name']
    #             home=r'E:老男孩课程day31ftp_projrct'                                                     #
    #             file_md5_path=os.path.join(home,'zhangzijie',file_md5)  #
    #             file_name_path = os.path.join(home, 'zhangzijie', file_name)
    #             upload_file_size=cmd_dic['size']           #所有文件信息都在上面取到的字典里《########
    #             exist=os.path.exists(file_md5_path)
    #             if not exist: #不续传
    #                 #我没有这个文件,你开始给我传
    #                 #设计状态码
    #                 response = {'code': 1001}
    #                 self.request.sendall(json.dumps(response).encode("utf8"))
    #                 f=open(file_md5_path,mode='wb')
    #
    #                 recv_size=0
    #                 #接受上传的文件内容
    #                 while recv_size<upload_file_size:
    #                     data=self.request.recv(1024)
    #                     f.write(data)   #写过来的东西都在内存中
    #                     f.flush()       #把内存中的东西刷到硬盘中
    #                     recv_size+=len(data)
    #                 f.close()
    #
    #                 #改名字,
    #                 #os模块的额rename在windows系统中的python2中会报错
    #                 #os.rename(file_md5_path,file_name_path)
    #                 #shutil模块在哪都不会报错,除了改文件名还可以该文件夹的名字
    #                 import shutil
    #                 shutil.move(file_md5_path,file_name_path)
    #
    #             else:
    #                 #怎么续传呢?你的告诉客户端我已经有多少了,你已经给我传了多少了,对方才能
    #                 #从断开的那里进行继续传
    #                 #根据文件路径获取大小
    #                 exist_szie=os.stat(file_md5_path).st_size
    #                 #定义一个协议
    #                 response={'code':1002,'size':exist_szie}
    #                 self.request.sendall(json.dumps(response).encode("utf-8"))
    #                 self.request.sendall(b'1002')
    #
    #                 f = open(file_md5_path, mode='ab')  #这里是追加
    #
    #                 # recv_size = 0     #这里的总大小就不在是0了,而是已经接受了的大小
    #                 recv_size=exist_szie         #这里有个方法,对于后面的变量名,类似的用到了前面的名字
    #                                              #可以不用重新再起名字,直接重新赋值把前面的覆盖掉就可以了
    #                 # 接受上传的文件内容
    #                 while recv_size < upload_file_size:
    #                     data = self.request.recv(1024)
    #                     f.write(data)  # 写过来的东西都在内存中
    #                     f.flush()  # 把内存中的东西刷到硬盘中
    #                     recv_size += len(data)
    #                 f.close()
    #
    #
    #             # print(cmd_dic)
    #
    #
    # server=socketserver.ThreadingTCPServer(('127.0.0.1',8001),Nbserver)
    # server.serve_forever()
    # #####################################################################################
    # 下面这个例子对方法进行归类
    # 开始编写上传部分
    import socketserver
    import os  #使用os模块的join方法
    import json
    cod={'1001':'开始上传','1002':'开始续传'}
    
    def upload(cmd_dic,conn):  #用conn代替了下面类中的self.request
        file_md5 = cmd_dic['md5']  #
        file_name = cmd_dic['file_name']
        home = r'E:老男孩课程day31ftp_projrct'  #
        file_md5_path = os.path.join(home, 'zhangzijie', file_md5)  #
        file_name_path = os.path.join(home, 'zhangzijie', file_name)
        upload_file_size = cmd_dic['size']  # 所有文件信息都在上面取到的字典里《########
        exist = os.path.exists(file_md5_path)
        if not exist:  # 不续传
            # 我没有这个文件,你开始给我传
            # 设计状态码
            response = {'code': 1001}
            conn.sendall(json.dumps(response).encode("utf8"))
            f = open(file_md5_path, mode='wb')
    
            recv_size = 0
            # 接受上传的文件内容
            while recv_size < upload_file_size:
                data = conn.recv(1024)
                f.write(data)  # 写过来的东西都在内存中
                f.flush()  # 把内存中的东西刷到硬盘中
                recv_size += len(data)
            f.close()
    
            # 改名字,
            # os模块的额rename在windows系统中的python2中会报错
            # os.rename(file_md5_path,file_name_path)
            # shutil模块在哪都不会报错,除了改文件名还可以该文件夹的名字
            import shutil
            shutil.move(file_md5_path, file_name_path)
    
        else:
            # 怎么续传呢?你的告诉客户端我已经有多少了,你已经给我传了多少了,对方才能
            # 从断开的那里进行继续传
            # 根据文件路径获取大小
            exist_szie = os.stat(file_md5_path).st_size
            # 定义一个协议
            response = {'code': 1002, 'size': exist_szie}
            conn.sendall(json.dumps(response).encode("utf-8"))
            conn.sendall(b'1002')
    
            f = open(file_md5_path, mode='ab')  # 这里是追加
    
            # recv_size = 0     #这里的总大小就不在是0了,而是已经接受了的大小
            recv_size = exist_szie  # 这里有个方法,对于后面的变量名,类似的用到了前面的名字
            # 可以不用重新再起名字,直接重新赋值把前面的覆盖掉就可以了
            # 接受上传的文件内容
            while recv_size < upload_file_size:
                data = conn.recv(1024)
                f.write(data)  # 写过来的东西都在内存中
                f.flush()  # 把内存中的东西刷到硬盘中
                recv_size += len(data)
            f.close()
    
    
    class Nbserver(socketserver.BaseRequestHandler):
        def handle(self):
            while 1:
                # 1 , 接受命令
                upload_cmd_bytes=self.request.recv(2048) #最大是8k
                # upload_cmd_str=json.loads(upload_cmd_bytes).decode("utf8")  #错误的写法
                cmd_dic = json.loads(upload_cmd_bytes.decode("utf8"))  #是字节有解码的方法《########
    
                if cmd_dic['cmd']=='upload':
                    upload(cmd_dic,self.request) #函数调用的时候,实参传self.request
                elif cmd_dic['cmd']=='download':
                    pass       #下载的代码
                
    
    
    server=socketserver.ThreadingTCPServer(('127.0.0.1',8001),Nbserver)
    server.serve_forever()
    ftp断点续传服务端

    客户端

    ##以下代码是梳理思路
    # import socket
    # import json
    # import hashlib
    # import os
    #
    # def file_md5(file_path):
    #     """
    #     对文件进行md5加密
    #     :param file_path:
    #     :return:
    #     """
    #     obj=open(file_path,mode='rb')
    #     m=hashlib.md5()       #实例化MD5
    #     for line in obj:
    #         m.update(line)    #使用md5的update方法
    #     obj.close()
    #     return m.hexdidest()
    #
    # sk=socket.socket()
    # sk.connect(('127.0.0.1',8001))
    # while 1:
    #     cmd=input("请输入命令:")
    #     """
    #     1,自定义协议
    #     {'cmd':'upload','file_path':'.....'}
    #     """
    #     #获取文件的相关信息
    #     file_path="/.../"
    #     file_md5_val=file_md5(file_path)
    #     file_name= os.path.basename(file_path)
    #     file_size=os.stat(file_path).st_size
    #     cmd_dict={'cmd':'upload','file_name':file_name,'size':file_size}
    #
    #     suload_cmd_bytes=json.dumps(cmd_dict).encode("utf8")
    #     sk.sendall(suload_cmd_bytes)  # 推荐使用sendall
    #
    #     #等待服务端的响应
    #     response=json.loads(sk.recv(8096).decode("utf-8")) #通过序列化与反序列化,最后又转化成字典的操作
    #                                                        #这种最后就非常方便
    #     if response['code']==1001:
    #         #从头开始传
    #         pass
    #     else:
    #         #从断点开始续传
    #         exist_zise=response['size']
    
    ###########################################################################################
    # 下面的例子可以运行,就是上传的文件需要指定
    # 开始编写上传部分
    # import socket
    # import json
    # import hashlib
    # import os
    #
    # def file_md5(file_path):
    #     """
    #     对文件进行md5加密
    #     :param file_path:
    #     :return:
    #     """
    #     obj=open(file_path,mode='rb')
    #     m=hashlib.md5()       #实例化MD5
    #     for line in obj:
    #         m.update(line)    #使用md5的update方法
    #     obj.close()
    #     return m.hexdigest()
    #
    # sk=socket.socket()
    # sk.connect(('127.0.0.1',8001))
    # while 1:
    #     cmd=input("请输入命令:")
    #     """
    #     1,自定义协议
    #     {'cmd':'upload','file_path':file_path}
    #     """
    #     #获取文件的相关信息
    #     file_path="hello.py"
    #     file_md5_val=file_md5(file_path)
    #     file_name= os.path.basename(file_path)
    #     file_size=os.stat(file_path).st_size
    #     cmd_dict={'cmd':'upload','file_name':file_name,'size':file_size,'md5':file_md5_val}
    #
    #     suload_cmd_bytes=json.dumps(cmd_dict).encode("utf8")
    #     sk.sendall(suload_cmd_bytes)  # 推荐使用sendall
    #
    #     #等待服务端的响应
    #     response=json.loads(sk.recv(8096).decode("utf8")) #通过序列化与反序列化,最后又转化成字典的操作
    #                                                        #这种最后就非常方便
    #     if response['code']==1001:
    #         #从头开始上传,文件迭代,一行一行发
    #         # with  open(file_path,mode='rb') as f:
    #         #     for line in f:
    #         #         sk.sendall(line)
    #         #发送可以有两种方式,另外一种如下:
    #         f=open(file_path,mode="rb")
    #         send_size=0
    #         while send_size< file_size: #不能等于,如果是等于,就会一直循环
    #             data=f.read(1024)
    #             sk.sendall(data)
    #             send_size+=len(data)
    #         f.close()
    #
    #
    #     else:
    #         #从断点开始续传
    #         exist_zise=response['size']
    #         f=open(file_path,'rb')
    #         f.seek(exist_zise) #seek跳到某个字节
    #         send_size=exist_zise  #已经发送的等于断点处的字节大小
    #         while send_size< file_size:  #已发的字节小于总大小
    #             data=f.read(1024)
    #             sk.sendall(data)
    #             send_size+=len(data)
    #         f.close()
    
    
    # #####################################################################################
    
    # 下面的例子对方法进行归类
    # 开始编写上传部分
    import socket
    import json
    import hashlib
    import os
    import time
    #先对函数进行归类
    
    
    
    def file_md5(file_path):
        """
        对文件进行md5加密
        :param file_path:
        :return:
        """
        obj=open(file_path,mode='rb')
        m=hashlib.md5()       #实例化MD5
        for line in obj:
            m.update(line)    #使用md5的update方法
        obj.close()
        return m.hexdigest()
    
    #进度条
    def jdt(size,total_size):
        val = int(size/total_size * 100)
        time.sleep(0.1)
        print('
    %s%%|%s' %(val,"#"*val,), end='')
    
    
    def send_file(exist_zise,file_tocal_size):
        f = open(file_path, 'rb')
        f.seek(exist_zise)  # seek跳到某个字节
        send_size = exist_zise  # 已经发送的等于断点处的字节大小
        while send_size < file_tocal_size:  # 已发的字节小于总大小
            data = f.read(1024)
            sk.sendall(data)
            send_size += len(data)
            jdt(send_size,file_tocal_size)            #调用进度条函数
        f.close()
    
    def upload(file_path):
        #获取文件的相关信息
        file_md5_val=file_md5(file_path)
        file_name= os.path.basename(file_path)
        file_size=os.stat(file_path).st_size
        cmd_dict={'cmd':'upload','file_name':file_name,'size':file_size,'md5':file_md5_val}
    
        suload_cmd_bytes=json.dumps(cmd_dict).encode("utf8")
        sk.sendall(suload_cmd_bytes)  # 推荐使用sendall
    
        #等待服务端的响应
        response=json.loads(sk.recv(8096).decode("utf8")) #通过序列化与反序列化,最后又转化成字典的操作
                                                           #这种最后就非常方便
        if response['code']==1001:
            #从头开始上传,文件迭代,一行一行发
            # with  open(file_path,mode='rb') as f:
            #     for line in f:
            #         sk.sendall(line)
            #发送可以有两种方式,另外一种如下:
            f=open(file_path,mode="rb")
            send_file(0,file_size)
    
        else:
            #从断点开始续传
            exist_zise=response['size']
            send_file(exist_zise,file_size)
    
    
    
    
    sk=socket.socket()
    sk.connect(('127.0.0.1',8001))
    while 1:
        user_onput=input("请输入命令:")
        cmd,file_path=user_onput.split('|',maxsplit=1)
        if cmd=='upload':
            upload(file_path)
        elif cmd=='download':
            pass           #如果elif特别多可以考虑使用反射
    ftp断点续传客户端
  • 相关阅读:
    Asp.net 后台添加CSS、JS、Meta标签(帮助类)
    Jquery 事件冒泡
    一个例子理解C#位移
    CodeSmith 创建Ado.Net自定义模版(四)
    .NET4.0下网站应用程序用UrlRewriter.dll重写无后缀路径 (在IIS7.5中的配置方法)
    用泛型的IEqualityComparer<T>接口去重复项
    Why MapReduce?
    SYN flood攻击介绍
    tmux使用方法详解
    理解Linux系统负荷
  • 原文地址:https://www.cnblogs.com/zhuhaofeng/p/9590954.html
Copyright © 2011-2022 走看看