HTTP协议的chunked编码以及用python实现chunked编码的下载


HTTP协议的chunked编码:

  一般的HTTP Headers 应该包含Content-Length来指名报文的长度。

    

  但是在有的时候,服务器无法确定HTTP回应的消息的大小,比如非常大的文件的下载,或者处理的逻辑比较复杂,需要一边处理一边实时生成消息(如果全部处理完再生成消息就会有很多缺点,比如用户收到响应的时间就会很长),这个时候服务器一般都使用chunked编码。此时,服务器不会带上Content-Length这个响应头,带上了两外一个头:Transfer-encoding:chunked。

  chunked编码使用若干个Chunk组成,由一个标明长度为0的chunk结束,每个Chunk有两部分组成,每个部分用回车换行隔开。在最后一个长度为0的Chunk中的内容是称为footer的内容,是一些没有写的头部内容。所以所谓的chunked编码是如下的格式:

  格式:

如果一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,那么,消息体由数量未定的块组成,并以最后一个大小为0的块为结束。

每一个非空的块都以该块包含数据的字节数(字节数以十六进制表示)开始,跟随一个CRLF (回车及换行),然后是数据本身,最后块CRLF结束。在一些实现中,块大小和CRLF之间填充有白空格(0x20)。

最后一块是单行,由块大小(0),一些可选的填充白空格,以及CRLF。最后一块不再包含任何数据,但是可以发送可选的尾部,包括消息头字段。消息最后以CRLF结尾。

  第一个chunk数据的字节数+/r/n+第一块chunk的数据 +/r/n+第二个chunk的数据的字节数+/r/n+第二块chunk的数据+n个chunk+/r/n+0+/r/n。

  因此,接收数据的时候,需要首先获取每一个chunk数据的字节长度,然后,跳过2个字节(/r/n),取出数据,然后,再跳过2个字节(/r/n),获取下一个chunk的长度,直到最后一个chunk,最后一个chunk一定是0,并且字节的长度都是十六进制形式传输,需要进行相应的转化成十进制,如果是gzip格式的数据,那么,在最后完成所有数据组合之后,需要再解压。

  

def decode_chunked(content):
    content = content.lstrip('\r') 
    content = content.lstrip('\n')
    temp = content.find('\r\n')
    strtemp = content[0:temp]
    readbytes = int(strtemp, 16)
    newcont = ''
    start = 2
    offset = temp + 2
    newcont = ''
    while(readbytes > 0):
        newcont += content[offset:readbytes + offset]
        offset += readbytes
        endtemp = content.find('\r\n', offset + 2)
        if(endtemp > -1):
            strtemp = content[offset + 2:endtemp]
            readbytes = int(strtemp, 16)
            if(readbytes == 0): 
                break
            else:
                offset = endtemp + 2
    
    content = newcont
    return content

def chunk_download(url, dest):
    fd = urllib.urlopen(url)
    chunk = decode_chunked(fd.read())
    fd.close()
    f = open(dest, 'w')
    f.write(chunk)
    f.close()

部分内容参考:

http://zh.wikipedia.org/wiki/%E5%88%86%E5%9D%97%E4%BC%A0%E8%BE%93%E7%BC%96%E7%A0%81

http://blog.csdn.net/xiqi8144/article/details/4413626

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM