Return 一个以 UTF-8 编码的 csv,带有来自 django 的 BOM
Return a csv encoded in UTF-8 with BOM from django
我正在尝试输出用户可以使用 excel 打开的 CSV 文件。我已经用 UTF-8 编码了所有字符串,但是当我用 excel 打开文件时,我看到了乱码。只有在使用 BOM 将文件转换为 UTF-8 后(在 windows 上使用记事本++),我才能正确显示内容。
我遵循 docs 中的这种模式:
def render_to_csv(self, request, qs):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="test.csv"'
writer = csv.writer(response, delimiter=',')
for row in qs.values_list(*self.fields_to_export):
writer.writerow([unicode(v).encode('utf-8') if v is not None else '' for v in row])
return response
BOM 在哪里适合所有这些?
顺便说一句,SO 上有 similar questions 个问题,但不幸的是没有一个得到回答。
编辑
在@Alastair McCormack 的基础上,我最终在文件开头明确添加了 BOM 字符。唯一的区别是我使用了编解码器包而不是对字节进行硬编码。感觉很尴尬,但确实有效!
import codecs
def render_to_csv(self, request, qs):
...
response.write(codecs.BOM_UTF8)
...
return response
在写入数据之前将 UTF-8 BOM 添加到响应对象:
def render_to_csv(self, request, qs):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="test.csv"'
# BOM
response.write("\xEF\xBB\xBF")
writer = csv.writer(response, delimiter=',')
…
StreamingHttpResponse
对于 csv
添加 UTF-8 BOM 或 \xEF\xBB\xBF
根据官方修改documents
import csv
import codecs
from django.utils.six.moves import range
from django.http import StreamingHttpResponse
class Echo(object):
def write(self, value):
return value
def iter_csv(rows, pseudo_buffer):
yield pseudo_buffer.write(codecs.BOM_UTF8)
writer = csv.writer(pseudo_buffer)
for row in rows:
yield writer.writerow(row)
def some_streaming_csv_view(request):
rows = (["Row {}".format(idx), str(idx)] for idx in range(65536))
response = StreamingHttpResponse(iter_csv(rows), Echo()), content_type="text/csv")
return response
给定的答案很好,但我想提示如何通过仅更改一行使 official examples from the Django
docs 在流的开头使用 UTF-8 BOM 字节序列:
import itertools
import codecs
streaming_content = itertools.chain([codecs.BOM_UTF8], (writer.writerow(row) for row in rows))
response = StreamingHttpResponse(streaming_content, content_type="text/csv")
在我的例子中,第一个 BOM_UTF8 字符在作为 http 响应返回时被自动删除。所以我不得不手动添加两个 BOM_UTF8 个字符。
response.write(codecs.BOM_UTF8)
response.write(codecs.BOM_UTF8)
response.write(encoded_csv_content)
我不知道这是什么原因,但也许它会对某人有所帮助,或者知道原因的人可以在评论中解释。
我正在尝试输出用户可以使用 excel 打开的 CSV 文件。我已经用 UTF-8 编码了所有字符串,但是当我用 excel 打开文件时,我看到了乱码。只有在使用 BOM 将文件转换为 UTF-8 后(在 windows 上使用记事本++),我才能正确显示内容。
我遵循 docs 中的这种模式:
def render_to_csv(self, request, qs):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="test.csv"'
writer = csv.writer(response, delimiter=',')
for row in qs.values_list(*self.fields_to_export):
writer.writerow([unicode(v).encode('utf-8') if v is not None else '' for v in row])
return response
BOM 在哪里适合所有这些?
顺便说一句,SO 上有 similar questions 个问题,但不幸的是没有一个得到回答。
编辑
在@Alastair McCormack 的基础上,我最终在文件开头明确添加了 BOM 字符。唯一的区别是我使用了编解码器包而不是对字节进行硬编码。感觉很尴尬,但确实有效!
import codecs
def render_to_csv(self, request, qs):
...
response.write(codecs.BOM_UTF8)
...
return response
在写入数据之前将 UTF-8 BOM 添加到响应对象:
def render_to_csv(self, request, qs):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="test.csv"'
# BOM
response.write("\xEF\xBB\xBF")
writer = csv.writer(response, delimiter=',')
…
StreamingHttpResponse
对于 csv
添加 UTF-8 BOM 或 \xEF\xBB\xBF
根据官方修改documents
import csv
import codecs
from django.utils.six.moves import range
from django.http import StreamingHttpResponse
class Echo(object):
def write(self, value):
return value
def iter_csv(rows, pseudo_buffer):
yield pseudo_buffer.write(codecs.BOM_UTF8)
writer = csv.writer(pseudo_buffer)
for row in rows:
yield writer.writerow(row)
def some_streaming_csv_view(request):
rows = (["Row {}".format(idx), str(idx)] for idx in range(65536))
response = StreamingHttpResponse(iter_csv(rows), Echo()), content_type="text/csv")
return response
给定的答案很好,但我想提示如何通过仅更改一行使 official examples from the Django
docs 在流的开头使用 UTF-8 BOM 字节序列:
import itertools
import codecs
streaming_content = itertools.chain([codecs.BOM_UTF8], (writer.writerow(row) for row in rows))
response = StreamingHttpResponse(streaming_content, content_type="text/csv")
在我的例子中,第一个 BOM_UTF8 字符在作为 http 响应返回时被自动删除。所以我不得不手动添加两个 BOM_UTF8 个字符。
response.write(codecs.BOM_UTF8)
response.write(codecs.BOM_UTF8)
response.write(encoded_csv_content)
我不知道这是什么原因,但也许它会对某人有所帮助,或者知道原因的人可以在评论中解释。