jQuery表单插件 + Ajax文件上传 + Rails

3
我正在使用jQuery表单插件处理一个包含一些文件字段的大型表单。后台是Ruby on Rails。

我遇到了一个问题,即使我认为我已经正确设置了POST请求类型为“text/javascript”,Rails仍然无法识别它。

表单如下:

<form id="listing_form" method="POST" enctype="multipart/form-data" action="/listings">
    <input type="text" size="30" name="listing[venue][phone]" id="listing_venue_phone"/>
    <input type="file" size="30" name="listing[venue][image]" id="listing_venue_image"/>
    ...plus tons of other fields

该JS代码如下:
$("#listing_form").ajaxForm({ dataType: 'script' });

我还声明了:

jQuery.ajaxSetup({ 
    'beforeSend': function(xhr) {xhr.setRequestHeader('Accept', 'text/javascript')}
});

请求已经到达控制器,但是Rails的respond_to块将其视为普通的html请求。此外,Firebug显示解析错误,并无法在控制台中显示请求和响应头。

如果我删除文件字段并仅POST文本字段,则respond_to块将处理该请求作为js请求,并正确执行create.js.erb文件。

我该如何使Rails正确响应请求呢?谢谢。


jQuery表单插件的dataType选项是jQuery的ajax方法中dataType选项的代理。这意味着XHR期望响应具有text/javascript内容类型。它与发送的内容无关。 - jason
感谢您的回复。我明白那部分内容,我已经编辑了我的帖子以澄清我的问题。 - cinematic
2个回答

4
由于JavaScript的安全限制,使用XHR无法发送带有(非空)文件字段的表单。 通常的解决方法是通过提交到隐藏的iframe来“伪造”ajax表单提交。我相信这也是jQuery表单插件所做的。 使Rails处理这些“虚假”的ajax表单提交的一种方法是在jQuery Form插件的beforeSubmit回调中添加一个特殊参数:
// ...
beforeSubmit: function(data) {
    data.push({name: 'accept_js', value: '1'});
}
// ...

然后在您的控制器中使用一个before过滤器来设置请求的格式为:js,当提交的数据包含特殊参数时:

before_filter :set_ajax_request

# ...

private
  def set_ajax_request
    request.format = :js if params[:accept_js] == '1'
  end

您的respond_to方法现在应该按预期工作。

嘿,感谢您的建议。但是,在添加它之前提交之间,accept_js参数就消失了,并且可能与iframe hack有关。正在追踪它... - cinematic
我按照这个视频教程 http://blog.edgecase.com/2009/6/15/ajax-file-uploads-made-easy-screencast 进行操作,并且成功了。基本上,我在表单中添加了一个 <$= hidden_field_tag :format, 'js' %>,并安装了插件。完美地解决了问题。感谢您的建议,它帮助我理解了正在发生的事情,并将我引向了正确的方向。 - cinematic

2

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