Django StreamingHttpResponse格式错误

时间:2016-02-26 09:04:12

标签: python django http boto3

我有简单的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."""

2 个答案:

答案 0 :(得分:0)

仍然不确定发生了什么。但是来自https://stackoverflow.com/a/8601118/2576817FileWrapper适用于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