Django - HTTPS поток файлов gzip, созданный на лету
Я использовал StringIO для создания файлового объекта, содержащего данные XML, затем я создал файл gzip с этим файловым объектом, у меня возникают проблемы при создании этого потока через HTTP с помощью django, размер файла не всегда фиксирован, а иногда он может быть большим Вот почему я выступил за HTTPStream вместо нормального 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 ответ
Я нашел решение обеих проблем: обработчик, который должен был быть передан HTTPStream, является StringIO, а не обработчиком Gzip, также обработчик StringIO доступен для поиска, так что я могу проверить размер данных после gzip, другой Хитрость заключается в том, чтобы вызвать метод close в обработчике gzip, чтобы он добавил crc32 и размер в файл gzip, в противном случае отправленные данные будут равны 0, поскольку StringIO не вызывает метод close, поскольку HTTPStream потребует открытия обработчика. для потоковой передачи данных сборщик мусора закроет его после завершения потока.
Это окончательный код:
# 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
Ура, надеюсь, это может помочь любому.