使用Django HttpResponse 返回二进制数据

10 投票
3 回答
21014 浏览
提问于 2025-04-17 21:28

我正在尝试让Django的HttpResponse返回二进制数据,但一直没有成功。我试了好几种方法,但都没用。

把字符串编码成ASCII格式可以用,只要二进制数据的值不超出ASCII字符范围,也就是小于0到255的值。但是用latin-1编码时也出现了同样的问题。

创建字节字符串的方式很好用,但如果数据中包含某些特定的值,就会出问题。例如,如果我的数据中有这些字节:"\xf6\x52",那么得到的结果会是不同的字节。奇怪的是,当我查看结果时,第一个字节\x\xf6会被转换成0xfffd。

我希望能得到一些反馈和帮助。

非常感谢!

-A-

3 个回答

1

这里有一个示例代码,展示了如何用Django来响应二进制数据(在我的例子中是Excel文件):

def download_view(request):
    # If you want to respond local file 
    with open('path/to/file.xlsx', 'rb') as xl:
        binary_data = xl.read()

    # Or if you want to generate file inside program (let's, say it will be openpyxl library)
    wb = openpyxl.load_workbook('some_file.xlsx')
    binary_object = io.BytesIO()
    wb.save(binary_object)
    binary_object.seek(0)
    binary_data = binary_object.read()

    file_name = f'FILENAME_{datetime.datetime.now().strftime("%Y%m%d")}.xlsx'

    response = HttpResponse(
        # full list of content_types can be found here
        # https://stackoverflow.com/a/50860387/13946204
        content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        headers={'Content-Disposition': f'attachment; filename="{file_name}"'},
    )
    response.write(binary_data)
    return response
5

在Django中返回二进制数据的一个灵活方法是先把数据用Base64编码。

Base64是一种把二进制数据转换成ASCII字符串格式的编码方式,它通过将数据转化为一种64进制的表示方法来实现。

因为Base64编码后的数据是ASCII格式,所以默认的HTTP响应内容类型text/html; charset=utf-8是可以正常工作的。

图片示例

Django

import base64
from io import BytesIO

from django.http import HttpRequest, HttpResponse
import PIL.Image


def image_test(request: HttpRequest) -> HttpResponse:
    file_stream = BytesIO()
    image_data = PIL.Image.open('/path/to/image.png')
    image_data.save(file_stream)
    file_stream.seek(0)
    base64_data = base64.b64encode(file_stream.getvalue()).decode('utf-8')
    return HttpResponse(base64_data)

网页浏览器

从Django获取到data后,可以用Base64数据来创建一个数据URL


// `data` fetched from Django as Base64 string
const dataURL = `data:image/png;base64,${data}`;
const newImage = new Image();
newImage.src = dataURL;
$('#ImageContainer').html(newImage);

JSON响应

Base64数据也可以作为JSON响应的一部分返回:

import base64
from io import BytesIO

from django.http import HttpRequest, JsonResponse
import PIL.Image

def image_test(request: HttpRequest) -> JsonResponse:
    file_stream = BytesIO()
    image_data = PIL.Image.open('/path/to/image.png')
    image_data.save(file_stream)
    file_stream.seek(0)
    base64_data = base64.b64encode(file_stream.getvalue()).decode('utf-8')
    json_data = dict()
    json_data['base64Data'] = base64_data
    return JsonResponse(json_data)
14
return HttpResponse(data, content_type='application/octet-stream')

对我来说有效。

撰写回答