使用jQuery的“表单插件”进行Ajax文件上传

5

我正在使用jQuery,并且希望通过Ajax上传文件。我进行了一些搜索,发现这是不可能的。

然而,有一个jQuery插件jQuery Form Plugin,可以让我们通过Ajax上传文件。

它运行得非常好,但我有一个特殊的问题。以下是我的代码:

$('#question-form').submit(function() {
    var serialAnswers = '';

    // Create a query string given some fields
    // Format of the query string : answers[0][fr_fr][0]=a1fr&answers[0][fr_fr][1]=2&answers[0][en_uk][0]=a1en&answers[0][en_uk][1]=6&...
    $('#question-answers > div').each(function(idx, elt) {
        $('div[lang]', $(elt)).each(function(idxLang, eltLang) {
            var lang = $(this).attr('lang');
            serialAnswers += 'answers[' + idx + '][' + lang + '][0]=' + $("[answerpart=display]", $(eltLang)).val();
            serialAnswers += '&answers[' + idx + '][' + lang + '][1]=' + $("[answerpart=value]", $(eltLang)).val() + '&';
        });
    });

    $(this).ajaxSubmit({
        datatype: "html",
        type: "POST",
        data: serialAnswers,
        url: $(this).attr("action"),
        success: function(retour) {
            $('#res-ajax').html(retour);
        }
    });

    return false;
});

如您所见,我需要将$.ajax调用替换为一个带有相同选项的$(this).ajaxSubmit()调用。此外,我需要根据一些字段创建一个查询字符串(代码中的serialAnswers),并将其传递给PHP代码。
当我没有文件要上传时,我曾经这样做。我只是序列化表单字段并添加了名为serialAnswers的查询字符串:
$.ajax({
    datatype: "html",
    type: "POST",
    data: $(this).serialize() + '&' + serialAnswers,
    url: $(this).attr("action")
    success: function(retour) {
        $("#res-ajax").html(retour);
    }
});

但是我的问题是,表单插件以这种方式传输我的附加数据(查询字符串)(在PHP文件中):

Array
(
    [question_heading_fr_fr] => something
    [question_heading_en_uk] => nothing
    [question_type] => 5
    [0] => a
    [1] => n
    [2] => s
    [3] => w
    [4] => e
    [5] => r
    [6] => s
    [7] => [
    [8] => 0
    [9] => ]
    [10] => [
    [11] => f
    [12] => r
    [13] => _
    [14] => f
    [15] => r
    [16] => ]
    ....
)

根据文档,我需要将一个JSON对象传递给数据选项,如下所示:
data: { key1: 'value1', key2: 'value2' }

但我不知道如何将我的查询字符串转换为JSON对象,如果在PHP端解释为数组会怎样。

有解决方案吗?

编辑:即使我使用一个iframe,我也不知道如何添加一个查询字符串,其中的信息并不来自表单(来自上面代码中的serialAnswer)。


Uploadify? - ifaour
1
如果可能的话,我宁愿不使用Flash。 - Romain Guidoux
3个回答

0

试试Uploadify。这是一个基于Flash的上传插件。它易于实现并支持多文件上传。


正如我告诉 @ifaour 的那样,我正在寻找一种非Flash解决方案。 而且我已经回答了我的问题,请看主题 ;) - Romain Guidoux

0

我不确定你具体想要什么,但你为什么不能这样做:

data: {'key1':$(this).serialize(),'key2': serialAnswers}

然后在 PHP 端解码 PHP,您可以执行以下操作:

json_decode($arr); //Where $arr is whatever the array is that gets passed

如果您需要返回一个JSON响应,只需执行以下操作:
json_encode($arr); //Where arr is an array you build within your script

我猜这就是你想要的。


serialAnswers是查询字符串。将这些数据传输到PHP时,它会转换为一个数组,所以我得到了:[key2] => answers[0][fr_fr][0]=something&answers[0][fr_fr][1]=2&answers[0][en_uk][0]=Other&... 因此,我无法使用json_decode对其进行解码。 - Romain Guidoux
嗯,你做得很好。我现在还没有什么想法,但我会考虑一下并回复你的 :) - jefffan24

0

编辑:我找到了一个新的解决方案,它可以正常工作 :)

我修改了jQuery表单插件。插件页面:http://jquery.malsup.com/form/#getting-started。脚本:https://github.com/malsup/form/raw/master/jquery.form.js

为了使用这个语法:

$('#myform').submit(function() {
    var queryString = 'answers[0][fr_fr][0]=a1fr&answers[0][fr_fr][1]=2&answers[0][en_uk][0]=a1en&answers[0][en_uk][1]=6';

    $(this).ajaxSubmit({
        dataType:  'html',
        data: queryString
    });

    return false; 
});

改为:

$('#myform').submit(function() {
    $(this).ajaxSubmit({
        dataType:  'html',
        data: {'key':'value' }
    });

    return false; 
});

我已经修改了插件代码。

找到这个:

var n,v,a = this.formToArray(options.semantic);
if (options.data) {
    options.extraData = options.data;
    for (n in options.data) {
        if(options.data[n] instanceof Array) {
            for (var k in options.data[n]) {
                a.push( { name: n, value: options.data[n][k] } );
            }
        }
        else {
            v = options.data[n];
            v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
            a.push( { name: n, value: v } );
        }
    }
}

并删除所有的if (options.data)及其内容。在这些行之后的几行中,找到以下内容:

var q = $.param(a);

然后在它后面添加这个:

if (options.data) {
    options.extraData = options.data;
    q += '&' + options.data;
}

在函数fileUpload()中,找到这个:
var extraInputs = [];
try {
    if (s.extraData) {
        for (var n in s.extraData) {
            extraInputs.push(
                $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
                    .appendTo(form)[0]);
        }
    }

    // Add iframe to doc and submit the form
    $io.appendTo('body');
    io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
    form.submit();
}

并将其替换为:

var extraInputs = [];
try {
    if (s.extraData) {
        var couples = s.extraData.split('&');
        for (var c=0 ; c < couples.length ; c++)
        {
            var couple = couples[c].split('=');
            extraInputs.push(
                $('<input type="hidden" name="'+couple[0]+'" value="'+couple[1]+'" />')
                    .appendTo(form)[0]);
        }
    }

    // add iframe to doc and submit the form
    $io.appendTo('body');
    io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
    form.submit();
}

现在由于这些修改,您可以同时上传图像并添加查询字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接