我有一个简单的Django视图,用于从亚马逊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时,我得到了不正确的文件格式(无法打开),甚至错误的大小(如果原始图像是317 be,输出木材大约为620 be)
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."""发布于 2016-02-29 09:19:09
还是不知道到底发生了什么。但是,来自https://stackoverflow.com/a/8601118/2576817的https://stackoverflow.com/a/8601118/2576817可以很好地处理boto3 StreamingBody响应类型。
如果有人有勇气解释这种模糊的行为,欢迎光临。
发布于 2016-03-31 18:22:04
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 responsehttps://stackoverflow.com/questions/35647476
复制相似问题