如何使用ajax执行将文件推送到浏览器的php函数?

时间:2015-07-29 21:46:11

标签: 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);

    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日志中

我做错了什么?

2 个答案:

答案 0 :(得分:3)

要下载文件,您必须使用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
);

然后修改AJAX返回的“成功”部分,如下所示:

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()

答案 1 :(得分:0)

@肖恩-金博尔,

您可能希望扩展MODX的基于类的处理器:

https://github.com/modxcms/revolution/blob/master/core/model/modx/processors/browser/file/download.class.php

它可以从任何媒体源下载,也可以根据需要进行检查。

在经理方面的实施是: https://github.com/modxcms/revolution/blob/master/manager/assets/modext/widgets/system/modx.tree.directory.js#L553

回到你的案例,这些例子可能会带给你一些想法。

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';

为此,我还建议您使用MODX的index.php主文件作为AJAX的连接器,这样处理器中的$modx对象也会继承访问权限。

http://www.virtudraft.com/blog/ajaxs-connector-file-using-modxs-main-index.php.html