【问题标题】:Return a csv encoded in UTF-8 with BOM from django使用来自 django 的 BOM 返回以 UTF-8 编码的 csv
【发布时间】:2015-07-29 02:23:24
【问题描述】:

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

我正在遵循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

【问题讨论】:

    标签: django csv utf-8


    【解决方案1】:

    就我而言,不知何故,第一个 BOM_UTF8 字符在作为 http 响应返回时会自动删除。所以我不得不手动添加两个 BOM_UTF8 字符。

    response.write(codecs.BOM_UTF8)
    response.write(codecs.BOM_UTF8)
    response.write(encoded_csv_content)
    

    我不知道这是什么原因,但也许它会帮助某人,或者知道原因的人可以在评论中解释。

    【讨论】:

    • 前段时间我遇到了同样的问题,在 SO 上问了一个问题并收到了这个答案:stackoverflow.com/a/42717677/1143392 这让我得到了同样的“解决方案”......
    【解决方案2】:

    给定的答案很好,但我想提示一下如何通过仅更改一行来使 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")
    

    【讨论】:

      【解决方案3】:

      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
      

      【讨论】:

        【解决方案4】:

        在写入数据之前将 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?
        • 不适用于 Python 3。response.write(codecs.BOM_UTF8) 将适用于 py2 和 py3。
        • 确实如此。这是因为codecs.BOM_UTF8 在 Py3 中返回一个字节字符串。
        猜你喜欢
        • 2018-02-28
        • 2012-07-18
        • 2020-01-25
        • 2018-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-14
        相关资源
        最近更新 更多