如何使用ajax执行将文件推送到浏览器的php函数?
我试图在一个php类中编写一个方法,它将使用ajax执行一个php函数,将文件推回到浏览器 它似乎试图将文件写入modx日志,在那里得到大量二进制垃圾 方法如下:如何使用ajax执行将文件推送到浏览器的php函数?,php,jquery,ajax,modx,Php,Jquery,Ajax,Modx,我试图在一个php类中编写一个方法,它将使用ajax执行一个php函数,将文件推回到浏览器 它似乎试图将文件写入modx日志,在那里得到大量二进制垃圾 方法如下: public function pushDocuments($formdata){ $data = $formdata['formdata']; $file = MODX_PROTECTED_STORAGE . $data['target']; $file_name = basename($file);
public function pushDocuments($formdata){
$data = $formdata['formdata'];
$file = MODX_PROTECTED_STORAGE . $data['target'];
$file_name = basename($file);
if (file_exists($file)) {
header("Content-Disposition: attachment; filename=\"$file_name\"");
header("Content-Length: " . filesize($file));
header("Content-Type: application/octet-stream;");
readfile($file);
};
$output = array(
'status' => 'success',
'error_messages' => array(),
'success_messages' => array(),
);
$output = $this->modx->toJSON($output);
return $output;
}
下面是jquery:
$('.btn-get-document').click(function(){
var target = $(this).attr('data-target');
var postdata = {"snippet":"DataSync", "function":"pushDocuments", "target": target}; // data object ~ not json!!
console.log('target = ' + target + postdata );
$.ajax({
type: "POST",
url: "processors/processor.ajax.generic/",
dataType : "json",
cache : false,
data: postdata, // posting object, not json
success: function(data){
if(data.status == 'success'){
console.log("SUCCESS status posting data");
}else if(data.status == 'error'){
console.log("error status posting data");
}
},
error: function(data){
console.log("FATAL: error posting data");
}
});
});
它正在运行脚本并在控制台中获得成功[因为我正在强制成功],但没有提示下载文件,二进制垃圾显示在modx日志中
我做错了什么?要下载文件,必须使用JS重定向到文件的位置。您不能通过AJAX提取文件内容并指示浏览器将这些内容保存为文件 您需要在结构上更改设置。例如,您的PHP脚本可以验证要下载的文件是否存在,然后向JS发送链接以下载该文件。大概是这样的:
if ( file_exists( $file )) {
$success_message = array(
'file_url' => 'http://example.com/file/to/download.zip'
);
}
$output = array(
'status' => 'success',
'error_messages' => array(),
'success_messages' => $success_message
);
success: function( data ) {
if ( data.status == 'success' ) {
location.href = data.success_messages.file_url;
} else if ( data.status == 'error' ) {
console.log( 'error status posting data' );
}
},
然后修改AJAX返回的“成功”部分,如下所示:
if ( file_exists( $file )) {
$success_message = array(
'file_url' => 'http://example.com/file/to/download.zip'
);
}
$output = array(
'status' => 'success',
'error_messages' => array(),
'success_messages' => $success_message
);
success: function( data ) {
if ( data.status == 'success' ) {
location.href = data.success_messages.file_url;
} else if ( data.status == 'error' ) {
console.log( 'error status posting data' );
}
},
由于您指向的是一个文件,只要文件的内容配置设置为“附件”,浏览器窗口实际上就不会出现在任何地方。通常,如果您指向浏览器内部未处理的任何文件(如ZIP文件),就会发生这种情况。如果您想控制它,以便它下载所有文件(包括浏览器可能使用插件处理的内容),您可以指向另一个PHP脚本,该脚本将发送适当的头,然后发送文件(类似于您发送头的方式,并在示例中使用readfile()
)。@sean kimball
您可能希望扩展MODX的基于类的处理器:
它可以从任何媒体源进行下载,如果需要,还可以进行访问检查
其在管理者端的实现是:
回到您的案例,这些例子可能会给您带来一些想法
JS示例:
$.ajax({
type: "POST",
// read my note down below about connector file
url: "assets/components/mypackage/connectors/web.php",
dataType : "json",
cache : false,
data: {
action: 'mypath/to/processor/classfile'
}
success: function(data){
},
error: function(data){
console.log("FATAL: error posting data");
}
});
处理器示例:
<?php
require_once MODX_CORE_PATH . 'model/modx/processors/browser/file/download.class.php';
class myDownloadProcessor extends modBrowserFileDownloadProcessor {
// override things in here
}
return 'myDownloadProcessor';
问题不在于jquery请求接收的是响应,而不是父浏览器窗口吗?看起来您试图同时向浏览器发送json响应和文件。这是行不通的。或者只是将一个隐藏的表单发布到iframehmm,问题是这些文件位于一个不可通过web访问的目录中。我不能只是转发一个指向该文件的链接。但问题的根源似乎是我无法通过ajax响应推送文件。。。对吗?@SeanKimball,我回答的最后一句话将解决这个问题。创建一个PHP脚本,该脚本可以引用该文件(可以是文件名,但是您需要能够识别它)。让该脚本输出标题并使用readfile()
发送数据。使用适当的标识符返回指向此PHP脚本的链接,而不是将指向文件的链接返回到AJAX。