Обработка загруженного файла Django как UTF-8 с универсальными символами новой строки

В моем приложении django я предоставляю форму, которая позволяет пользователям загрузить файл. Файл может быть в разных форматах (Excel, CSV), поступать с разных платформ (Mac, Linux, Windows), и быть закодированными в различных кодировках (ASCII, UTF-8).

Для целей этого вопроса предположим, что у меня есть представление, которое получает request.FILES ['file'] , который является экземпляром InMemoryUploadedFile , который называется файлом . Моя проблема в том, что объекты InMemoryUploadedFile (например, файл ):

  1. Не поддерживают кодировку UTF-8 (я вижу \ xef \ xbb \ xbf в начало файла, который, как я понимаю, является флагом, означающим «этот файл имеет формат UTF-8»).
  2. Не поддерживает универсальные символы новой строки (которые, вероятно, потребуются большинству файлов, загружаемых в эту систему).

Проблема усложняется тем, что я хочу передать файл в модуль python csv , который изначально не поддерживает Unicode. Я с радостью приму ответы, позволяющие избежать этой проблемы - как только я получу, что django хорошо работает с UTF-8, я уверен, что смогу заставить csv сделать то же самое. (Точно так же не обращайте внимания на требование поддержки Excel - я жду, пока CSV заработает, прежде чем приступить к синтаксическому анализу файлов Excel.)

Я пробовал использовать StringIO , mmap , ] кодек и любой из множества способов доступа к данным в объекте InMemoryUploadedFile . Каждый подход давал разные ошибки, ни одна из них пока не была идеальной. Это показывает часть кода, который, как мне кажется, подошел ближе всего:

import csv
import codecs

class CSVParser:
    def __init__(self,file):
        # 'file' is assumed to be an InMemoryUploadedFile object.
        dialect = csv.Sniffer().sniff(codecs.EncodedFile(file,"utf-8").read(1024))
        file.open() # seek to 0
        self.reader = csv.reader(codecs.EncodedFile(file,"utf-8"),
                                 dialect=dialect)
        try:
            self.field_names = self.reader.next()
        except StopIteration:
            # The file was empty - this is not allowed.
            raise ValueError('Unrecognized format (empty file)')

        if len(self.field_names) <= 1:
            # This probably isn't a CSV file at all.
            # Note that the csv module will (incorrectly) parse ALL files, even
            # binary data. This will catch most such files.
            raise ValueError('Unrecognized format (too few columns)')

        # Additional methods snipped, unrelated to issue

Обратите внимание, что я не потратил слишком много времени на сам алгоритм синтаксического анализа, поэтому он может быть очень неэффективным, сейчас меня больше беспокоит кодирование в работать как положено.

Проблема в том, что результаты также не кодируются, несмотря на то, что они заключены в оболочку Unicode codecs.EncodedFile .

РЕДАКТИРОВАТЬ: Оказывается, приведенный выше код действительно Работа. codecs.EncodedFile (file, "utf-8") - это билет. Оказывается, я думал, что это не сработало, потому что используемый мной терминал не поддерживает UTF-8. Живи и учись!

12
задан Cœur 8 February 2018 в 15:39
поделиться