我有简单的Django视图,用于从Amazon s3下载文件。 通过本地保存文件进行测试是正常的:
def some_view(request):
res = s3.get_object(...)
try:
s3_file_content = res['Body'].read()
with open("/Users/yanik/ololo.jpg", 'wb') as f:
f.write(s3_file_content)
# file saved and I can view it
except:
pass
切换到StreamingHttpResponse
时,我的文件格式不正确(无法打开),甚至尺寸错误(如果原稿是317kb图像,则输出木材大约为620kb)
def some_view(request):
res = s3.get_object(...)
response = StreamingHttpResponse(res['Body'].read(), content_type=res['ContentType'])
response['Content-Disposition'] = 'attachment;filename=' + 'ololo.jpg'
response['ContentLength'] = res['ContentLength']
return response
尝试了许多不同的设置,但到目前为止没有任何对我有用。输出文件已损坏。
我设法获得更多首次亮相的信息。如果我将第一个样本中的文件写入方法从'wb'
更改为'w'
模式,我将使用与StreamingHttpResponse
相同的输出(第一个视图将生成相同的损坏文件)。
所以看起来我必须告诉http标题我的输出是binary
格式
现在我明白了这个问题。 但仍然没有解决方案。
res['Body'].read()
返回bytes
类型,StreamingHttpResponse
遍历这些字节,返回字节代码。所以我的相当传入的字节'...\x05cgr\xb8=:\xd0\xc3\x97U\xf4\xf3\xdc\xf0*\xd4@\xff\xd9'
强制转换为数组,如:[ ... , 195, 151, 85, 244, 243, 220, 240, 42, 212, 64, 255, 217]
,然后像连接字符串一样下载。屏幕截图:http://take.ms/JQztk
如您所见,列表元素到底。
StreamingHttpResponse.make_bytes
"""Turn a value into a bytestring encoded in the output charset."""
答案 0 :(得分:0)
仍然不确定发生了什么。但是来自https://stackoverflow.com/a/8601118/2576817的FileWrapper
适用于boto3 StreamingBody
响应类型。
欢迎有人有勇气解释这种模糊行为。
答案 1 :(得分:0)
https://docs.djangoproject.com/en/1.9/ref/request-response/#streaminghttpresponse-objects
StreamingHttpResponse需要一个迭代器。我想如果你的文件是二进制(图像),那么StreamingHttpResponse不是最好的解决方案,或者你应该创建该文件的块。
Bytearray是一个迭代器,但也许你想要的不是字节/字符。
我不确定你的文件是否是基于行的文本数据,但如果是,你可以创建一个生成器来迭代文件,如对象:
def line_generator(file_like_obj):
for line in file_like_obj:
yield line
并将该生成器提供给StreamingHttpResponse:
some_view(request):
res = s3.get_object(...)
response = StreamingHttpResponse(line_generator(res['Body']), ...)
return response