Javascript -> 下载以 ISO-8859-1 / Latin1 / Windows-1252 编码的 CSV 文件

Javascript -> Download CSV file encoded in ISO-8859-1 / Latin1 / Windows-1252

我开发了一个小工具来从 Amazon CSV 订单数据中提取运输数据。到目前为止它有效。这是 JS Bin 的简单版本:http://output.jsbin.com/jarako

为了打印 stamps/shipping 标签,我需要一个文件来上传到 Deutsche Post 和其他包裹服务。我使用了一个在 Whosebug 上找到的小函数 saveTextAsFile。到目前为止一切都很好。输出文本区域或下载的文件中没有错误显示特殊字符 (äöüß...)。

所有这些德语 post / 包裹服务网站只接受 latin1 / iso-8859-1 编码文件上传。但是我下载的文件总是utf-8。如果我上传它,所有特殊字符 (äöüß...) 都会出错。

我该如何更改?我仍然搜索了很多。我已经尝试过,即:

正在将工具的字符集设置为 iso-8859-1:

<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

但结果是:现在我在输出文本区域和下载的文件中仍然有错误的特殊字符。如果我把它上传到 post 站点,我仍然会得到更多的错误字符。另外,如果我在 CODA 编辑器中检查编码,它仍然说下载的文件是 UTF-8。

saveTextAsFile函数使用var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});。那里可能有设置下载字符集的方法!?

function saveTextAsFile()
{
    var textToWrite = $('#dataOutput').val();
    var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
    var fileNameToSaveAs = "Brief.txt";

    var downloadLink = document.createElement("a");
    downloadLink.download = fileNameToSaveAs;
    downloadLink.innerHTML = "Download File";
    if (window.webkitURL != null)
    {
        // Chrome allows the link to be clicked
        // without actually adding it to the DOM.
        downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
    }
    else
    {
        // Firefox requires the link to be added to the DOM
        // before it can be clicked.
        downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
        downloadLink.onclick = destroyClickedElement;
        downloadLink.style.display = "none";
        document.body.appendChild(downloadLink);
    }

    downloadLink.click();
}

无论如何,必须有一种方法可以下载其他编码的文件,因为该网站使用它自己。我从中下载 CSV 文件的亚马逊网站采用 UTF-8 编码。但是如果我在 CODA 中检查它,从那里下载的 CSV 文件是 Latin1 (iso-8859-1)...

向下滚动到更新以获得真正的解决方案!

因为没有得到答案,所以我搜索了越来越多。看起来 Javascript 中没有解决方案。我在 javascript 中生成的每个测试下载都是 UTF-8 编码的。看起来 Javascript 仅适用于 UNICODE / UTF-8 或其他编码(可能)仅适用于使用以前的 HTTP 传输再次传输数据的情况。但是对于在客户端上运行的 Javascript,不会发生额外的 HTTP 传输,因为数据仍在客户端上..

我现在已经帮助我在我的服务器上构建了一个小的 PHP 脚本,我通过 GET 或 POST 请求将数据发送到该脚本。它将编码转换为 latin1 / ISO-8859-1 并将其下载为文件。这是一个具有正确编码的特殊字符的 ISO-8859-1 文件,我可以将其上传到上述邮政和包裹服务网站,一切看起来都不错。

latin-download.php:(将 PHP 文件本身也保存在 ISO-8859-1 中非常重要,以使其工作!!)

<?php
$decoded_a = urldecode($_REQUEST["a"]);
$converted_to_latin = mb_convert_encoding($decoded_a,'ISO-8859-1', 'UTF-8');
$filename = $_REQUEST["filename"];
header('Content-Disposition: attachment; filename="'.$filename.'"; content-type: text/plain; charset=iso-8859-1;');
echo $converted_to_latin;
?>

在我的 javascript 代码中我使用:

<a id="downloadlink">Download File</a>

<script>
var mydata = "this is testdata containing äöüß";

document.getElementById("downloadlink").addEventListener("click", function() {
    var mydataToSend = encodeURIComponent(mydata);
    window.open("latin-download.php?a=" + mydataToSend + "&filename=letter-max.csv");
}, false);
</script>

对于更大数量的数据,您必须从 GET 切换到 POST...

2016 年 2 月 8 日更新

半年后,现在我在 PURE JAVASCRIPT 中找到了解决方案。使用 inexorabletash/text-encoding. This is a polyfill for Encoding Living Standard. The standard includes decoding of old encodings like latin1 ("windows-1252"), but it forbids encoding into these old encoding types. So if you use the browser implemented window.TextEncoder function it does offer only UTF encoding. BUT, the polyfill solution 提供了一种传统模式,它也允许编码为 latin1 等旧编码。

我是这样用的:

<!DOCTYPE html>
<script>
// 'Copy' browser build in TextEncoder function to TextEncoderOrg (because it can NOT encode windows-1252, but so you can still use it as TextEncoderOrg()  )
var TextEncoderOrg = window.TextEncoder;   
// ... and deactivate it, to make sure only the polyfill encoder script that follows will be used 
window.TextEncoder = null;  

</script>
<script src="lib/encoding-indexes.js"></script>  // needed to support encode to old encoding types
<script src="lib/encoding.js"></script>  // encording polyfill

<script>

function download (content, filename, contentType) {
    if(!contentType) contentType = 'application/octet-stream';
        var a = document.createElement('a');
        var blob = new Blob([content], {'type':contentType});
        a.href = window.URL.createObjectURL(blob);
        a.download = filename;
        a.click();
}

var text = "Es wird ein schöner Tag!";

// Do the encoding
var encoded = new TextEncoder("windows-1252",{ NONSTANDARD_allowLegacyEncoding: true }).encode(text);

// Download 2 files to see the difference
download(encoded,"windows-1252-encoded-text.txt");
download(text,"utf-8-original-text.txt");

</script>

encoding-indexes.js 文件大约有 500kb 大,因为它包含了所有的编码表。因为我只需要 windows-1252 编码,为了我的使用,我删除了这个文件中的其他编码。所以现在只剩下 632 字节了。

您不能强迫网络服务器以给定的编码向您发送数据,只能礼貌地询问。仅转换为所需格式的方法是正确的方法。

如果您想避免使用 PHP 脚本,您可能会在创建 Blob:

时指定编码作为参数
var textFileAsBlob = new Blob(textToWrite, {
  type: 'text/plain;charset=ISO-8859-1', 
  encoding: "ISO-8859-1"
});

有关详细信息,请参阅 Specifying blob encoding in Google Chrome

问题不在于编码,而是特殊字符在某些应用程序中显示错误的事实,例如微软 Excel。 UTF-8 适合显示所有特殊的德语字符。您可以通过在 csv 前面添加字节顺序标记 (BOM) 来解决此问题。

const BOM = "\uFEFF" 
let csvData = BOM + csvData
const blob = new Blob([csvData], { type: "text/csv;charset=utf-8" });

解决方案基于this github post