如何使用jQuery AJAX导入/上传文件?

时间:2012-11-01 作者:EkoJR

我一直遇到在AJAX中添加文件的问题,以便服务器AJAX功能可以处理数据。如何使$\\u文件的传递与默认操作(内置到表单元素中)相同?

HTML Form

<form id="frmImport" name="frmImport" method="post" enctype="multipart/form-data" >
    <input id="file_import" name="importData" type="file" />
    <br/>
    <button id="btn_import" type="submit" >Import</button>
</form>

JavaScript

    jQuery(document).ready(function($) {
    //This is already setup and sent from the server side, and is
    // is used to prevent unauthorized users from uploading data.
    var importnonce = "3x4mpl3f4k3n0nc3"; 

    $(\'#frmImport\').submit(function(e) {
        e.preventDefault();

        // CHECK FOR ANY ERRORS HERE.
        // IF ERRORS EXIST, RETURN FALSE TO END OPERATIONS.

        var formData = new FormData();
        formData.append(\'action\', \'ajax_handler_import\');
        formData.append(\'_ajax_nonce\', importNonce);

        // Issue occures here. PHP gets a string \'[object FormData]\'.
        var importFiles = $(\'#file_import\')[0].files;
        formData.append(\'uploadFiles\', importFiles);

        jQuery.ajax({
            url: ajaxurl,
            type: \'POST\',
            cache: false,
            contentType: false,
            processData: false,

            data: formData,

            beforeSend: function(jqXHR, settings) {
                console.log("Haven\'t entered server side yet.");
            },
            dataFilter: function(data, type) {
                // Used to parse data, and possibly check for errors.
                console.log("JSON string echoed back from server side.");
            },
            success: function(data, textStatus, jqXHR) {
                console.log("Back from server-side!");
                // Checking errors that may have been caught on the server side that
                // normally wouldn\'t display in the error Ajax function.
                if (data.msg != \'success\') {
                    alert(data.error);
                }
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.log("A JS error has occurred.");
            },
            complete: function(jqXHR, textStatus) {
                console.log("Ajax is finished.");
            }
        });

        return false;
    });
});

PHP Server/Handler

<?php
class server {
    function ajax_import_handler() {
        check_ajax_referer("ajax_handler_import");

        $rtnData = new stdClass();
        $rtnData->msg = \'success\'; //For signifying Server errors
        $rtnData->error = \'\'; //For displaying custom error messages or using the try/catch method

        //Do Stuff
        foreach ($_FILES as $key => $value) {
            //GET FILE CONTENT
            $file_array[$key] = json_decode(file_get_contents($value[\'tmp_name\']));
        }

        // Do more stuff with file(s).

        // Add stuff to $rtnData.

        echo json_encode($rtnData);
    }
}
?>

3 个回复
最合适的回答,由SO网友:EkoJR 整理而成

这是我能够找到的解决方案,实际上我看到了很多常见的错误。

JS中没有正确附加文件dataFilter: function() 可以替换为dataType: \'json\'.可替换为event.stopPropagation() &;e.preventDefault().

HTML

<form id="form_import" name="form_import" method="post" enctype="multipart/form-data" action >
    <input id="file_import" name="import_data" type="file" />
    <br/>
    <button id="btn_import" type="submit" >Import</button>
</form>
JavaScript
jQuery(document).ready(function($){
    // PHP files could echo an Nonce. This however localizes scripts.
    var importNonce = localizedData.import_nonce;

    $(\'#form_import\').submit( function( event ) {
        event.stopPropagation(); // Stop stuff happening
        event.preventDefault(); // Totally stop stuff happening

        var formData = new FormData();
        var importFiles = $(\'#file_import\')[0].files;

        // For EACH file, append to formData.
        // NOTE: Just appending all of importFiles doesn\'t transition well to PHP.
        jQuery.each( importFiles, function( index, value ) {
            var name = \'file_\' + index;
            formData.append( name, value )
        });

        formData.append( \'action\', \'ajax_file_import\' );
        formData.append( \'_ajax_nonce\', importNonce );

        jQuery.ajax({
            url: ajaxurl,
            type: \'POST\',
            data: formData,
            cache: false,
            dataType: \'json\', // This replaces dataFilter: function() && JSON.parse( data ).
            processData: false, // Don\'t process the files
            contentType: false, // Set content type to false as jQuery will tell the server its a query string request


            beforeSend: function( jqXHR, settings ){
                // (OPTIONAL) Alt. AJAX concept.
                // Removes the old IFrame if any.
                var element = document.getElementById(\'import_IF\');
                if ( element !== null ){
                    element.parentNode.removeChild( element );
                }
                // END (OPTIONAL).
            },
            success: function( data, textStatus, jqXHR ) {
                console.log( \'Return from PHP AJAX function/method.\' );

                // Do stuff with data.values

                // (OPTIONAL) Alt. AJAX concept.
                // Required for downloading in AJAX.
                var paramStr = \'\';
                paramStr += \'?_ajax_nonce=\' + data._ajax_nonce;
                paramStr += \'&action=\'      + data.action;
                paramStr += \'&filename=\'    + data.filename;

                var elemIF = document.createElement("iframe");
                elemIF.id = \'import_IF\'
                elemIF.style.display = "none";
                elemIF.src = ajaxurl + paramStr;

                document.body.appendChild(elemIF);
                elemIF.parentNode.removeChild(elemIF);
                // END (OPTIONAL).
            },
            complete: function(jqXHR, textStatus){
                console.log( \'AJAX is complete.\' );

                // (OPTIONAL) Alt. AJAX concept.
                // Clean up IFrame.
                var element = document.getElementById(\'import_IF\');
                if ( element !== null ){
                    element.parentNode.removeChild( element );
                }
                // END (OPTIONAL).
            }
        });// End AJAX.
    });// End .submit().
});
PHP
<?php
class server {
    public function __construct() {
        // Example for adding script.
        add_action( \'admin_enqueue_scripts\', array( $this, \'enqueue_example\' ) );
        add_action( \'wp_ajax_ajax_file_import\', array( $this, \'ajax_import_example\' ) );
    }

    public funtion enqueue_example() {
        wp_register_script(
            \'example-js\',
            FILE_URL,
            array(),
            VERSION,
            false
        );
        wp_enqueue_script( \'example-js\' );

        $data = array(
            \'import_nonce\'  => wp_create_nonce( \'ajax_file_import_nonce\' ),
        );

        wp_localize_script( \'example-js\', \'localizedData\', $data );
    }

    public function ajax_import_example() {
        check_ajax_referer( \'ajax_file_import_nonce\' );

        $raw_content = array();
        $i = 0;
        while ( isset( $_FILES[ \'file_\' . $i ] ) ) {
            $file_arr = $_FILES[ \'file_\' . $i ];
            $file_content = file_get_contents( $file_arr[\'tmp_name\'] );
            $raw_content[]  = json_decode( $file_content );
            $i++;
        }

        $new_data = array();
        // Do Stuff with new data.
        update_option( \'example_database\', $new_data );

        // (OPTIONAL) Add data to return to AJAX Success
        $rtn_data = array(
            \'action\'               => \'apl_import\',
            \'_ajax_nonce\'          => wp_create_nonce( \'alt_ajax\' ),
        );
        echo json_encode( $rtn_data );
        // END (OPTIONAL).

        die();
    }
}
?>

SO网友:Mridul Aggarwal

我没有试过,但我想你需要补充一下FormData 直接作为对象data 参数像这样的

    var ajaxData = new FormData();

    ajaxData.append( \'action\', \'ajax_handler_import\' );
    ajaxData.append( \'_ajax_nonce\', importNonce );
    // or maybe skip the nonce for now

    jQuery.each($(\'#fileImportData\')[0].files, function(i, file) {
        ajaxData.append(\'file-\'+i, file);
    });
其余代码按原样运行

SO网友:Bainternet

传统意义上的Ajax是XMLHttpRequest,它不允许您编码本地文件并将其发送到服务器。

通过“ajax”方式进行上传的常见方法是,要么使用Flash swf处理同一页面上的上传,要么使用目标为不可见1x1 iframe的表单。

下面是一个非常类似的问题good answer 看看你是怎么做到的

结束

相关推荐

自动完成/自动建议未显示jQuery下拉菜单

我已将一个字段设置为“自动完成/自动建议”,但键入时未显示下拉列表。我可以看到管理ajax。php请求和Chrome Developer Tools的Network选项卡中返回的数据,似乎可以很好地检索建议。我真的不知道如何进一步排除故障,并解决问题。Javascript如下所示: <script type=\"text/javascript\"> var se_ajax_url = \'<?php echo admin_url(\'admin-ajax.php\'