php - 如何修复通过 ajax 下载的文件名的编码?
问题描述
php get_dokument 中有一个 php-script,它会生成一个名为“Инструкция_по_работе_с_сайтом.pdf”(西里尔文)的文件并将其输出到浏览器。如果我直接在浏览器中访问 get_dokument,我会得到一个名为“Инструкция_по_работе_с_сайтом.pdf”的文件。如果我使用 ajax 帖子
var xhr = new XMLHttpRequest();
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8');
xhr.send($.param({ ajax:1,document_id:document_id,company_id:company_id,action:action}));
我在响应标头中看到的内容:
Cache-Control: must-revalidate
Connection: keep-alive
Content-Description: File Transfer
Content-Disposition: attachment; filename="Инструкция_по_работе_с_сайтом.pdf"
Content-Length: 143647
Content-Type: application/pdf; charset=utf-8
Date: Mon, 07 Sep 2020 08:11:02 GMT
Expires: 0
Pragma: public
Server: nginx/1.14.0 (Ubuntu)
但该文件以“Ð_нÑ_Ñ_Ñ_Ñ_кÑ_иÑ__по_Ñ_абоÑ_е_Ñ__Ñ_айÑ_ом.pdf”的名称打开。使用 base64 没有帮助
完整代码:PHP:
$name = 'Инструкция_по_работе_с_сайтом';
$filename_pdf = $name.'.pdf';
$path = './uploads/dokuments/';
header('Content-Description: File Transfer');
header("Content-Type: application/pdf; charset=utf-8");
header('Content-Disposition: attachment; filename="'.$filename_pdf.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($path.$filename_pdf));
readfile($path.$filename_pdf);
unlink($path.$filename_pdf);
js:
var xhr = new XMLHttpRequest();
xhr.open('POST', '<?=site_url('cabinet/dokuments/get_dokument');?>', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
if (this.status === 200) {
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
alert(filename);
var type = xhr.getResponseHeader('Content-Type');
var blob;
if (typeof File === 'function') {
try {
blob = new File([this.response], filename, { type: type });
} catch (e) { /* Edge */ }
}
if (typeof blob === 'undefined') {
blob = new Blob([this.response], { type: type });
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location.href = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location.href = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
};
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8');
xhr.send($.param({ ajax:1,document_id:document_id,company_id:company_id,action:action}));
解决方案
推荐阅读
- javascript - 在传单中使用测量工具时禁用弹出窗口
- c++ - 在 Visual Studio 调试器中,如何从内存中打印一系列字节?
- linux - 远程到本地滚动备份脚本
- wagtail - 如何通过鹡鸰添加电话链接?
- html - Socket.io 在 html 页面中显示从客户端接收到的数据
- python - pytest 是否有类似谷歌测试的非致命 EXPECT_* 行为?
- javascript - 在句柄更改时通过状态响应传递值
- reactjs - 我应该如何按照单一责任模式处理组件状态
- python - `tf.keras.layers.ActivityRegularization` 是如何工作的以及如何正确使用它?
- windows - 非交互地写入注册表而不覆盖