【发布时间】:2017-03-04 19:51:57
【问题描述】:
在我的 Apache Web 服务器配置中,我添加了对不属于标准六的两个标头的支持:
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Expose-Headers: Content-Disposition,X-Filename
我的文件导出 CGI 脚本打印包含这两个字段数据的标题,例如:
...
print "Content-Disposition: attachment; filename=%s\n" % (out_fn)
print "X-Filename: %s\n" % (out_fn)
...
我的客户端 AJAX 调用尝试在 AJAX 请求成功时检索 Content-Disposition 的值:
var export_form = new FormData();
export_form.append("settings", JSON.stringify(settings));
export_form.append("format", format);
$.ajax({
url: "services/export_data.py",
type: "POST",
async: true,
cache: false,
data: export_form,
processData: false,
contentType: false,
success: function(response, textStatus, jqXHR) {
console.log("success");
console.log(jqXHR.getAllResponseHeaders());
console.log(jqXHR.getResponseHeader('Content-Disposition'));
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("export_form submit failed:", jqXHR.status, jqXHR.statusText);
console.log(jqXHR);
}
});
我在客户端的测试请求完成并运行success 回调,我在response 字段中取回文件数据,但我得到null 的响应标头Content-Disposition。
换句话说,console.log(jqXHR.getAllResponseHeaders()) 的样本结果是:
Date: Sat, 04 Mar 2017 19:42:27 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips mod_python/3.5.0- Python/2.7.5 mod_perl/2.0.10 Perl/v5.16.3
Transfer-Encoding: chunked
Content-Type: application/pdf
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Disposition,X-Filename
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
而console.log(jqXHR.getResponseHeader('Content-Disposition'))的结果为空:
null
为什么我的 AJAX 请求无法检索到 Content-Disposition 的值,当我通过 Web 服务器配置明确提供它并且在响应中正确设置它时?
为了解决换行问题,我使用sys.stdout.write 来获得对输出的更多控制,例如:
sys.stdout.write("Content-Type: %s\n" % (mime_type))
sys.stdout.write("Content-Disposition: attachment; filename=%s\n" % (output_fn))
sys.stdout.write("X-Filename: %s\n" % (output_fn))
sys.stdout.write("Content-Description: File to download\n\n")
with open(out_fn, "rb") as out_fh:
sys.stdout.write(out_fh.read())
不幸的是,通过console.log(jqXHR.getResponseHeader('Content-Disposition')) 和console.log(jqXHR.getResponseHeader('X-Filename'))(它们都是null)的AJAX 响应仍然看不到这两个标头。
【问题讨论】:
-
响应中是否包含实际的标头(您可以在浏览器的开发者控制台中看到它们)吗?
-
@AlexReynolds 当您使用 python
print时,您不必添加新的换行符,因为print实际上添加了它。您确定mod_headersApache 模块已启用吗?当我从另一个域进行 AJAX 调用并返回标头时,它在我身上完美地工作,无需换行符字符串终止。请在此处查看屏幕截图:zikro.gr/dbg/srv/apache-custom-cors-headers-1.png。我不能给你一个链接,因为我在虚拟机上运行 Apache 服务器,但是如果你想看的话,我可以提供它。 -
我已经打开了运行 Apache 2.4 的虚拟机,并提供了一个工作示例。您可以在此处zikro.gr/dbg/srv/apache-headers 尝试使用 AJAX 调用的工作脚本,如果您检查源代码,您将看到 url 在不同的服务器上。
print和sys.stdout.write都在工作并在控制台窗口中输出标题。请在此处查看控制台屏幕截图zikro.gr/dbg/srv/apache-custom-cors-headers-2.png。您是否检查了日志文件是否存在潜在错误? AJAX 调用是否返回200 Success? -
你在写
Unfortunately, these two headers were still not visible to the AJAX response。它们实际上是否在响应中并且对 Javascript 代码根本不可见,或者它们根本不包含在响应中?您能否发布带有标头的原始响应以及可能包含的数据的前几个字节?您可以使用浏览器的开发者控制台或 curl 等工具来完成。 -
@AlexReynolds 你能提供整个 python cgi 脚本吗?请记住,如果您在标头之前写入任何其他内容,HTTP 响应将不会捕获您的标头。如果在脚本编写标题之前没有输出,那么使用
sys.stdout.write的示例应该可以工作。 (另外我假设您在使用sys.stdout之前使用import sys导入sys库)。
标签: jquery ajax apache http-headers