从服务器获取文件时 JavaScript Blob 编码错误

Wrong encoding on JavaScript Blob when fetching file from server

在 SPA 网站(.NET Core 2,SPA React 模板)中使用来自 C# 的 FileStreamResult,我从我的端点请求一个文件,这在 C# 中触发了这个响应:

var file = await _docService.GetFileAsync(token.UserName, instCode.Trim()
.ToUpper(), fileSeqNo);
string contentType = MimeUtility.GetMimeMapping(file.FileName);
var result = new FileStreamResult(file.File, contentType);
var contentDisposition = new ContentDispositionHeaderValue("attachment");
Response.Headers[HeaderNames.ContentDisposition] = 
contentDisposition.ToString();
return result;

返回的响应是使用 msSaveBlob 处理的(特别是对于 MS,但这是一个问题,即使我使用 createObjectURL 和不同的浏览器(是的,我已经尝试了多种解决方案,但是none 似乎有效)。这是我用来发送请求并从服务器接收 PDF FileStreamResult 的代码。

if (window.navigator.msSaveBlob) {
  axios.get(url).then(response => {
      window.navigator.msSaveOrOpenBlob(
          new Blob([response.data], {type: "application/pdf"}),
          filename);
  });

问题是我得到的返回 PDF 文件不知何故编码错误。所以PDF打不开。

我试过在 type: {type: "application/pdf; encoding=UTF-8"} 的末尾添加编码,这在不同的帖子中都有建议,但是,这没有什么区别。

对比我用不同方式抓取的PDF文件,我可以清楚地看到编码是错误的。大多数特殊字符都不正确。响应header表示,PDF文件应该在UTF-8,但我不知道如何实际查找和检查。

虽然不知道 axios,但从它的 readme page 看来它使用 JSON 作为默认值 responseType。这可能会改变内容,因为它现在被视为文本(当 axios 无法转换为实际的 JSON 对象并保留响应数据的 string/text 源时,axios 可能会退出)。

PDF 应作为二进制数据加载,即使它既可以是 8 位二进制内容也可以是 7 位 ASCII - 在任何情况下都应被视为字节流,来自 Adobe PDF reference sec. 2.2.1 :

PDF files are represented as sequences of 8-bit binary bytes. A PDF file is designed to be portable across all platforms and operating systems. The binary rep resentation is intended to be generated, transported, and consumed directly, without translation between native character sets, end-of-line representations, or other conventions used on various platforms. [...].

Any PDF file can also be represented in a form that uses only 7-bit ASCII [...] character codes. This is useful for the purpose of exposition, as in this book. However, this representation is not recommended for actual use, since it is less efficient than the normal binary representation. Regardless of which representation is used, PDF files must be transported and stored as binary files, not as text files. [...]

因此,为了解决发生的转换,我建议在执行请求时尝试指定配置条目 responseType

axios.get(url, {responseType: "arraybuffer"}) ...

或这种形式:

axios({
  method: 'get',
  url: url,
  responseType:'arraybuffer'
})
.then( ... )

如果您确定 mime-type 在此过程中得到保留,您也可以直接转到 response-type blob