使用Django HttpResponse 返回二进制数据
我正在尝试让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')
对我来说有效。