jQuery ajaxForm返回.json文件

11

我在Rails中有一个模型创建表单,同时也通过ajax返回JSON。 迄今为止我的代码如下:

$('#new_stem').ajaxForm({ //#new_stem is my form
  dataType: 'json',
  success: formSuccess
});

function formSuccess(stemObj) {
  //does stuff with stemObj
}

我有一个带文件上传器的多部分表单(但我不确定这是否相关)。

当我提交表单时,它正常工作(我的模型被正确创建并呈现为JSON),但是与其让formSuccess函数处理JSON,Firefox会提示下载“stems.json”(我的茎创建操作路径)。

这是什么原因造成的?怎样解决?不确定是否是问题的一部分,但我的表单中没有提交按钮,而是有一个链接和点击处理程序,调用$('#new_stem).submit()

谢谢大家!

编辑:Firebug告诉我标题包含以下内容:

Etag        "b53e5247e7719cf6b1840e2c6e68781c"
Connection      Keep-Alive
Content-Type    application/json; charset=utf-8
Date        Mon, 03 May 2010 02:19:31 GMT
Server      WEBrick/1.3.1 (Ruby/1.8.7/2010-01-10)
X-Runtime       241570
Content-Length  265
Cache-Control   private, max-age=0, must-revalidate

增加一个cookie头部


我认为这与文件上传有关。如果我直接使用Firefox导航到一个json文件,同样的提示框会弹出,我知道为了通过ajax上传文件,必须创建一个单独的iframe来提交表单。我认为iframe只是在之后导航到该json文件,而Firefox试图将其处理为下载。是否有任何服务器端选项可以更改,使其不被视为下载? - Lowgain
8个回答

8
为了防止浏览器下载 .json 文件,将 Content-type 头设置为 "text/html"。 PHP:
header("Content-type: text/html");

ASP.NET MVC:

return Json(obj, "text/html");

在 JavaScript 中,您需要解析文本结果,例如:
$(".addform").ajaxSubmit({
            url: "file.php",
            type: "POST",
            dataType: "text",
            iframe: true,
            success: function (text) {
                var data = $.parseJSON(text);
            },
            error: function (xmlRequest, textStatus, errorThrown) {
                alert(errorThrown);
            }
        });

完美运作。


1
当你的响应包含字符<(或在某些情况下为&)时,这将会导致问题,因为HTML解析器会正确地进行一些错误纠正。 - user123444555621

2

这个插件可以让你使用ajax提交MultiPart表单。

如果你想使用Ajax的'success:'选项,你需要使用Ajax提交表单。目前你正在使用submit()函数,它基本上只是传统方式提交表单。你能够看到json数据作为下载文件或在你的浏览器中看到,这意味着这正发生着。

如果你需要多部分功能,你需要使用该插件(否则只需使用常规Ajax函数)。

使用该插件,你应该像这样使用:

$("#SubmitButton").click(function() {

  $.ajaxFileUpload({
    url: serverurl,
    secureuri: false,
    fileElementId: elementId,
    dataType: 'json',
    success: function(data, status) {
      /* show success message */
    },
    error: function(data, status, e) {
      /* handle error */
    }
  });
});

如果您不想上传文件,有一种更简单的方法可以实现。
$("#SubmitButton").click(function() {
  $.post('YOUR_URL', $("#FormName").serialize(), function(data) {
    alert(data.name); // John
  }, "json"); //specify return data is going to be json
});

ajaxForm插件确实允许文件上传,并且这些上传成功运行。我相信它也会钩入.submit()事件,但我改变了我的点击处理程序来调用.ajaxSubmit()。不幸的是,结果相同! - Lowgain
我也打算试用这个插件! - Lowgain
这个插件似乎不能让我控制我的文章数据结构。由于这是Rails,它需要以特定的方式发送。 - Lowgain
请查看以下链接:https://dev59.com/3UbRa4cB1Zd3GeqP5PWX -- 使用 $('#frmSearch').bind,这个人成功地让相同的事情工作了。请在页面上阅读正确的答案。如果您正在使用 ajaxSubmit,我希望您也同时使用 jQuery 表单插件(http://jquery.malsup.com/form)。 - DMin
现在我觉得提交不是问题,而是Firefox将返回的.json文件处理为下载(因为ajax上传是通过iframe完成的)。我需要想出一种方法让Firefox在浏览器中打开它,而不是作为下载。 - Lowgain
文件扩展名.json是Mozilla Firefox网络浏览器使用的。自版本3.0起,用于以JSON格式备份书签。通常,我会使用PHP从常规的.php页面输出正确格式的JSON字符串,而jQuery可以毫无问题地接收并将其处理为JSON。 - DMin

2

虽然并不完全是我想解决的问题,但我能够提出一种略微不同的解决方案,以满足我的需求!

由于ajax文件上传是通过iframes完成的,问题在于在iframe加载.json文件后,Firefox将其解释为下载,并打开了下载提示。我相信我可以在服务器设置上进行调整以防止这种情况发生,但我已经投入了足够多的时间。

所以我做的是将输出渲染为文本而不是json,因为我只是真正寻找一个id号码而已。我的代码现在看起来像:

$(document).ready(function() {
  $('#continue-upload').click(function() {
    $('#new_stem').ajaxSubmit({
      dataType: 'text', //'json',
      success: formSuccess
    });
  });
});

我需要的ID号码也被包裹在

标签中,因此在我的结果函数中我需要将其去除。

现在它已经实现了我想要的功能,太棒了!


2

实际上,该插件的ajaxSubmit代码有些不太优雅。为了使ajaxSubmit正常工作(截至撰写本文时),您的服务器必须返回JSON数据,其content-type为text/html。该插件将自动删除<pre>标签等(请参见源代码)。我猜当他们试图让隐藏的iframe返回json时,他们决定将json视为文本并从iframe中解析它。


1
听起来好像是因为响应头的Content-Type不正确,因此浏览器不知道该怎么处理它。它应该是application/json。您可以使用FirebugNet面板来确定实际的响应头。

我使用Firebug查看了传入的头文件,其中包含Content-Type application/json; charset=utf-8 - Lowgain
好的,我会更新问题以包含那个...当下载提示突然弹出时,这是人们首先想到的事情之一。Content-Disposition怎么样?没有attachment吗? - BalusC
头文件看起来不错。我猜测你可以尝试一下将dataType改成jsonp,但是这通常仅用于跨域JSON请求,因为它会改变JSON处理方式。 - BalusC
看起来ajaxForm不支持jsonp。 - Lowgain
你最终通过将 dataType 更改为 text 来修复它。我觉得这很奇怪。其他浏览器呢?这不是一些 Firefox 配置问题吗? - BalusC

0

或许这会有所帮助

$('#cpFileUpload').ajaxForm({
        dataType: 'html',           
        success: function(data) {           
            eval(data);                 
            if (data.result == false) {
                alert('error on server side');
            } else {                
                // do what you want
            }
        }       
    }); 

在服务器端,输出必须像这样(只有这个输出或者没有任何其他文字在body标签中)。
var data = {result: true, html: 'ok'}

虽不太美观,但能正常工作


0
你是否取消了 submit 事件的默认操作?听起来表单实际上正在被提交(以经典方式 - 换句话说,Firefox 实际上正在导航到表单中指定的页面)。

据我所知,ajaxForm 已经处理了这个问题。 - BalusC
啊——我从来没有用过 ajaxForm。也许启动 Fiddler 看看是否生成了多个请求? - josh3736

0

简单方法:

$('#new_stem').ajaxForm({ dataType: 'text', complete: function(xhr) { data = JSON.parse(xhr.responseText); } });


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