使用来自django的BOM返回以UTF-8编码的csv

时间:2023-01-06 07:26:40

I'm trying to output a CSV file that the user could open with excel. I've encoded all string in UTF-8 but when I opened the file with excel I see jibrish. Only after converting the file to UTF-8 with BOM (using notepad++ on windows) I was able to display the content properly.

我正在尝试输出用户可以使用excel打开的CSV文件。我已经用UTF-8编码了所有字符串,但是当我用excel打开文件时,我看到了jibrish。只有在使用BOM将文件转换为UTF-8(在Windows上使用notepad ++)之后,我才能正确显示内容。

I'm following this pattern from the 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

Where does to BOM fit into all of this ?

物料清单适用于所有这些?

BTW, There are similar questions on SO but unfortunately non of them are answered.

顺便说一句,在SO上也有类似的问题,但遗憾的是,没有人回答这些问题。

EDIT

building on @Alastair McCormack, I ended up explicitly adding the BOM characters at the begining of the file. Only difference is i used the codecs package instead of hard coding the bytes. Feels awkward but does the trick !

在@Alastair McCormack的基础上,我最终明确地在文件的开头添加了BOM字符。唯一的区别是我使用了编解码器包而不是硬编码字节。感觉很尴尬,但做的伎俩!

import codecs

def render_to_csv(self, request, qs): 
  ... 
  response.write(codecs.BOM_UTF8)
  ...
  return response

2 个解决方案

#1


3  

Add the UTF-8 BOM to the response object before you write your data:

在编写数据之前,将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=',')
  …

#2


1  

StreamingHttpResponse for csv add UTF-8 BOM or \xEF\xBB\xBF

用于csv的StreamingHttpResponse添加UTF-8 BOM或\ xEF \ xBB \ xBF

Modified from official 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

#1


3  

Add the UTF-8 BOM to the response object before you write your data:

在编写数据之前,将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=',')
  …

#2


1  

StreamingHttpResponse for csv add UTF-8 BOM or \xEF\xBB\xBF

用于csv的StreamingHttpResponse添加UTF-8 BOM或\ xEF \ xBB \ xBF

Modified from official 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