Javascript для CSV экспортной проблемы кодировки

Мне нужно экспортировать массив javascript в файл Excel и загрузить его. Я делаю это в этом коде. Данные - это массив объектов javascript.

var csvContent = "data:text/csv;charset=utf-8,";
data.forEach(function(dataMember, index)
{
    dataString = dataMember.join(",");
    csvContent += index < data.length ? dataString+ "\n" : dataString;
}); 

var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "upload_data" + (new Date()).getTime() + ".csv");
link.click();

Все это прекрасно работает, пока у меня не появятся строковые свойства с неанглийскими символами, такими как испанский, арабский или иврит. Как я могу сделать экспорт со всеми этими значениями не ASCII?

11 ответов

Вы должны добавить спецификацию UTF-8 в начале текста, например:

var csvContent = "data:text/csv;charset=utf-8,%EF%BB%BF";

Это работало для меня с Excel 2013.

Демо Фиддл

Вы можете сначала добавить спецификацию, использовать этот код и попробовать

var BOM = "\uFEFF"; 
var csvContent = BOM + csvContent;

и затем напишите заголовки файла с данными: "text/csv;charset=utf-8"

Excel действительно плохо распознает кодировку, особенно Excel на OSX.

Лучшим решением было бы кодировать ваш CSV в кодировке Excel по умолчанию: windows-1252 (также называемой ANSI, которая в основном является подмножеством ISO-8859-1).

Я разместил полный пример того, как это сделать, по адресу: https://github.com/b4stien/js-csv-encoding.

Две основные части - это stringencoding (для кодирования содержимого вашего CSV в windows-1252) и FileSaver.js (для загрузки созданного BLOB-объекта).

Это выглядит как:

var csvContent = 'éà; ça; 12\nà@€; çï; 13',
    textEncoder = new TextEncoder('windows-1252');


var csvContentEncoded = textEncoder.encode([csvContent]);
var blob = new Blob([csvContentEncoded], {type: 'text/csv;charset=windows-1252;'});
saveAs(blob, 'some-data.csv');

Нет необходимости использовать encodeURIComponentметод и склейте фрагменты строки данных. Просто вставьте символ спецификации перед строкой.

      const data = 'öäüÖÄÜ';
const BOM = '\uFEFF';
const blob = new Blob([BOM + data], { type: 'text/csv;charset=utf-8' });

const url = window.URL.createObjectURL(blob);
const linkElem = document.createElement('a');
linkElem.href = url;
linkElem.click();

Опция 1

использование iconv-lite библиотека и закодировать ваш вывод в ascii, прежде чем отправить его обратно пользователю. Пример:

var iconv = require('iconv-lite');
buf = iconv.encode(str, 'win1255'); // return buffer with windows-1255 encoding

Вариант 2

Напишите в заголовке файла заголовок спецификации в кодировке UTF-8. Пример:

res.header('Content-type', 'text/csv; charset=utf-8');
res.header('Content-disposition', 'attachment; filename=excel.csv'); 
res.write(Buffer.from('EFBBBF', 'hex')); // BOM header

// rest of your code

Вариант 3

Используйте формат base64 url ​​как data:text/csv;base64,77u/Zm9vLGJhcg0KYWFhLGJiYg==, Этот метод будет работать и на стороне клиента (IE10+, FF, Chrome, Opera, Safari).

Например:

window.location = "data:text/csv;base64,77u/" + btoa("foo,bar\r\naaa,bbb");
 data=`"red","मुकेश"`
 var processdata = "data:text/csv;charset=utf-8,%EF%BB%BF" + encodeURIComponent(data);

Как -то нашел Tab-Separated-CSV с кодировкой utf-16le с BOM работает на WIN/MAC Excel

последовал за ответом b4stien, но немного изменил архив:

var csvContent = 'éà; ça; 12\nà@€; çï; 13',
    textEncoder = new TextEncoder('utf-16le');
var csvContentEncoded = textEncoder.encode([csvContent]);
var bom = new Uint8Array([0xFF, 0xFE]);
var out = new Uint8Array( bom.byteLength + csvContentEncoded.byteLength );
out.set( bom , 0 );
out.set( csvContentEncoded, bom.byteLength );
var blob = new Blob([out]);
saveAs(blob, 'some-data.csv');

с тестами Linux /usr/bin/file:

Little-endian UTF-16 Unicode text, with very long lines, with CRLF line terminators

Я смог решить свою проблему с помощью ответа /questions/14366372/dobavlenie-spetsifikatsii-utf-8-v-stroku-blob/14366393#14366393

      const json2csv = require('json2csv');
const csvExport = (req, res) => {
    var csvContent = json2csv({ data, fields })

    res.setHeader('Content-Type', 'text/csv')
    // just prepend the '\ufeff' to your csv string value
    return res.status(200).send('\ufeff' + csvContent)
}

B4stien, спасибо тебе за ответ! После тестирования нескольких решений, основанных на кодировке "utf8", кодирование windows-1252 - единственное решение, которое позволило мне сохранить акцент в Excel 365!

Манец, ответ b4stien и его ссылка были очень полезны для моего случая: я должен экспортировать французские и немецкие данные в файл csv: ни одно решение, основанное на utf8, не сработало... Только его решение, которое использует "ANSI" (окно -1252) кодировщик...

Я привожу его пример кода, и вы можете скачать соответствующие encoding-indexes.js, encoding.js и FileSaver.js по ссылке...

    <!doctype html>
    <html>

    <head>
        <meta charset="utf-8">
        <script type="text/javascript" src="encoding-indexes.js"></script>
        <script type="text/javascript" src="encoding.js"></script>
        <script type="text/javascript" src="FileSaver.js"></script>
    </head>

    <body>
        <a href="#" id="download-csv">Click me to download a valid CSV !</a>

        <script type="text/javascript">
            var csvContent = 'éà; ça; 12\nà@€; çï; 13',
                textEncoder = new CustomTextEncoder('windows-1252', {NONSTANDARD_allowLegacyEncoding: true}),
                fileName = 'some-data.csv';

            var a = document.getElementById('download-csv');
            a.addEventListener('click', function(e) {
                var csvContentEncoded = textEncoder.encode([csvContent]);
                var blob = new Blob([csvContentEncoded], {type: 'text/csv;charset=windows-1252;'});
                saveAs(blob, fileName);
                e.preventDefault();
            });
        </script>
    </body>

    </html>

Тем не менее, поскольку Excel относительно открыт в поддержке языков и форматов, я не исключаю, что UTF8 не поддерживается в моей среде разработки из-за способа его установки...

Примечание: я тестирую его с Firefox, Chrome и IE 11 на Windows 7, с Excel 365...

Это решение, которое сработало для меня

Ссылка: Экспорт файла CSV в кодировке

      var csv = 'السلام عليكم, Student name\n';
        
var hiddenElement = document.createElement('a');
        //workaround to support encoding
hiddenElement.href = **'data:text/csv;charset=utf-8,%EF%BB%BF'+encodeURIComponent(csv);**

hiddenElement.download = 'Course Students Progress - ' + new Date().toLocaleString() + '.csv';
hiddenElement.click();

Чтобы экспортировать CSV-файл, содержащий многобайтовые символы, и сделать его читаемым в текстовом редакторе и Excel на нескольких платформах ОС (Windows, Linux, MacOS), должны применяться следующие правила:

  1. Разделите поле табуляцией вместо запятой (чтобы Excel в MacOS мог правильно отображать сгенерированный файл CSV)
  2. Кодируйте строку / содержимое с помощью UTF-16 little endian (UTF16-LE) вместо UTF-8
  3. Добавьте метку порядка байтов (BOM) 0xFEFF, как указано в разделе 3.2 RFC2781, в начале сериализованного потока, чтобы явно предоставить "подпись" контента, закодированного с помощью UTF16-LE.

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

Другие вопросы по тегам