Web API 操作 returns FileContentResult,如果保存为 .csv,将打开为乱码,而如果保存为 .txt,则正常。为什么?

Web API action returns FileContentResult that, if saved as .csv, will open as gibberish , while if as .txt, is ok. Why?

我正在使用 ASP.NET Web API 通过 http 获取响应导出文件。 为此,我返回一个 FileContentResult 对象,如:

return File(Encoding.UTF8.GetBytes(fileContents.ToString()), "text/plain; charset=UTF-8");

在遇到编码问题几分钟后,我使用 google 的高级 REST 客户端执行访问 Web api 控制器的操作,文件下载正常。

嗯,不完全是。我最初希望它是 sent/downloaded 作为 .csv 文件。 如果我将 http 请求内容类型设置为“text/csv”并且 File() 调用也将响应的内容类型设置为 "text/csv",Advanced REST客户端将正确显示内容,但 excel 将其作为乱码数据打开。

如果我只是将内容类型更改为“text/plain”,将其保存为 .txt 文件(保存后必须重命名,不知道为什么要保存为 _.text-plain,而保存为 csv 时使用 .csv 扩展名),最后在 Excel 中执行导入如此处所述 Excel 导入文本向导,然后 excel 正确打开文件。

为什么 .csv 打开时是乱码,而 .txt 却不是?对于打开 .csv,没有像 .txt 文件那样的导入向导(我不知道)。

提供下面的一些来源:

StringBuilder fileContents = new StringBuilder();

//csv header
fileContents.AppendLine(String.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, fileData.Select(fileRecord => fileRecord.Name)));

//csv records
foreach (ExportFileField fileField in fileData)
    fileContents.AppendLine(fileField.Value);

return File(Encoding.UTF8.GetBytes(fileContents.ToString()), "text/plain; charset=UTF-8");

根据要求,两个文件的二进制内容。 纯文本 (.txt) 版本(将在 excel 中打开的版本,使用导入):

和 .csv 文件(excel 将用垃圾数据打开的文件):

(文件相同,屏幕截图的裁剪不一样...)

文件的二进制内容显示了一个正确的带有希伯来字符的 utf-8 编码的 CSV 文件。如果,如您在评论中所述,Excel 不允许您在打开 CSV 文件时更改其猜测的文件编码,那是 Excel 本身的不当行为(如果您愿意,可以称之为错误).

您的选择是:使用 LibreOffice (http://www.libreoffice.org/),该电子表格组件允许您自定义打开 CSV 文件的设置。

另一种方法是编写一个小程序来明确地将您的文件转换为 excel 所期望的编码 - 如果您安装了 Python3 解释器,您可以输入:

python -c "open('correct.csv', 'wt', encoding='cp1255').write(open('utf8.csv', encoding='utf8').read())"

但是,如果您的默认 Windows 编码不是用于处理希伯来语的 cp1255,正如我在上面假设的那样,那将无济于事 excel,但会给您带来不同的胡言乱语:-)在这种情况下,您应该使用可以正确处理不同编码的程序。

(注意。在 Windows 中有一个 Python 对默认系统编码 return 的调用,但我忘了它是什么,而且它不容易被谷歌搜索)

令我惊讶的是,尝试通过浏览器执行请求 而不是使用 google 的高级 REST 客户端,单击刚刚下载的文件作品! Excel正确打开。所以问题一定出在 ARC 上。

无论如何,由于该过程不会使用浏览器以外的 http 客户端来完成...我的问题已经解决了。同样,在 ARC 的输出屏幕中,文件显示正确。我不知道为什么点击它会在 Excel 中打开它 "gets corrupted"。

奇怪。

我能够通过保存包含带有 BOM 的希腊字符的文件来重现该问题。双击尝试使用系统的语言环境(希腊语)导入文件。手动导入时,Excel 检测代码页并提供使用 65001 (UTF8) 代码页。

此行为奇怪,但不是错误。文本文件不包含有助于检测其代码页的指示,也不可能进行猜测。仅包含 A-Z 字符并保存为 1252 的 ASCII 文件与使用 1253 保存的 ASCII 文件相同。这就是为什么 Windows 使用系统代码页,这是用于所有非 Unicode 程序的本地 and 个文件。

当您双击文本文件时,Excel 无法询问您正确的编码 - 这很快就会变得乏味。相反,它会使用您的区域设置和系统代码页打开文件。在您的机器上创建的 ASCII 文件是使用您系统的代码页保存的,因此这种行为是合乎逻辑的。 非程序员 提供给您的文件也可能使用您所在国家/地区的代码页进行保存。程序员通常将所有内容都切换为美国英语,问题就是这样开始的。您的 REST 客户端可能使用大多数程序员使用的拉丁编码将文本保存为 ASCII。

当您将文本文件导入一个空的 sheet 时,Excel 会询问您要做什么。它尝试通过检查 可能 与文件内容匹配的 BOM 或代码页来检测代码页,并在导入对话框中显示猜测 一起 预览。小数点和列分隔符仍然是由您的区域设置提供的(猜不出来)。 UTF8 通常很容易猜到——文件以 BOM 开头或包含 NUL 条目。

虽然 ASCII 代码页更难。将我的希腊文文件保存为 ASCII 会导致日文猜测。我想这就是适合你的英语幽默。