Django - 即时创建的gzip文件的HTTP流

时间:2014-08-18 13:36:53

标签: python django gzip http-streaming

我使用StringIO创建一个保存xml数据的文件对象,然后我用这个文件对象创建了一个gzip文件,我在用django通过HTTP制作这个流时遇到了麻烦,文件大小并不总是固定的,有时它可能很大,这就是为什么我选择HTTPStream而不是normale HTTP响应。我无法弄清楚如何发送文件长度,因为文件对象不可搜索。

谢谢你的帮助,干杯!

这是我的代码:

# Get the XML string
xml_string = get_xml_cebd(cebds)

# Write the xml string to the string io holder
cebd_xml_file.write(xml_string)

# Flush the xml file buffer
cebd_xml_file.flush()

# Create the Gzip file handler, with the StringIO in the fileobj
gzip_handler = gzip.GzipFile(
    fileobj=cebd_xml_file,
    filename=base_file_name + '.xml',
    mode='wb'
)

# Write the XML data into the gziped file
gzip_handler.write(cebd_xml_file.getvalue())
gzip_handler.flush()

# Generate the response using the file warpper, content type: x-gzip
# Since this file can be big, best to use the StreamingHTTPResponse
# that way we can garantee that the file will be sent entirely
response = StreamingHttpResponse(
    gzip_handler,
    content_type='application/x-gzip'
)

# Add content disposition so the browser will download the file
response['Content-Disposition'] = ('attachment; filename=' +
    base_file_name + '.xml.gz')

# Content size
gzip_handler.seek(0, os.SEEK_END)
response['Content-Length'] = gzip_handler.tell()

1 个答案:

答案 0 :(得分:0)

我找到了两个问题的解决方案,应该传递给HTTPStream的处理程序是StringIO,而不是Gzip处理程序,StringIO处理程序也是可搜索的,这样我就可以检查数据的大小了gzip,另一个技巧是在gzip处理程序上调用close方法,因此它会将crc32和size添加到gzip文件中,否则发送的数据将为0,因为StringIO不会调用close方法,因为HTTPStream将需要处理程序打开以流式传输数据,垃圾收集器将在Stream完成后关闭它。

这是最终代码:

# Use cStringIO to create the file on the fly
cebd_xml_file = StringIO.StringIO()

# Create the file name ...
base_file_name = "cebd"

# Get the XML String
xml_string = get_xml_cebd(cebds)

# Create the Gzip file handler, with the StringIO in the fileobj
gzip_handler = gzip.GzipFile(
    fileobj=cebd_xml_file,
    filename=base_file_name + '.xml',
    mode='wb'
)

# Write the XML data into the gziped file
gzip_handler.write(xml_string)

# Flush the data
gzip_handler.flush()

# Close the Gzip handler, the close method will add the CRC32 and the size
gzip_handler.close()

# Generate the response using the file warpper, content type: x-gzip
# Since this file can be big, best to use the StreamingHTTPResponse
# that way we can garantee that the file will be sent entirely
response = StreamingHttpResponse(
    cebd_xml_file.getvalue(),
    content_type='application/x-gzip'
)

# Add content disposition so the browser will download the file, don't use mime type !
response['Content-Disposition'] = ('attachment; filename=' +
    base_file_name + '.xml.gz')

# Content size
cebd_xml_file.seek(0, os.SEEK_END)
response['Content-Length'] = cebd_xml_file.tell()

# Send back the response to the request, don't close the StringIO handler !
return response

欢呼,希望这可以帮助任何人。