使用Backbone上传文件

时间:2011-06-28 00:18:27

标签: javascript ruby-on-rails backbone.js

我在Rails应用程序中使用Backbone.js,我需要将文件上传作为其中一个Backbone模型的一部分。

我不相信Backbone允许开箱即用的多部分文件上传。有没有人设法通过一些插件或其他外部lib工作?我如何扩展Backbone.js来支持这个?

5 个答案:

答案 0 :(得分:20)

使用不同方法试用几个月后回答我自己的问题。我的解决方案如下(使用Rails)。

对于需要上传文件的任何表单,我会设置data-remote="true"enctype="multipart/form-data"并添加rails.jsjquery.iframe-transport.js

使用rails.js设置data-remote="true"可以让我绑定到ajax:success并成功创建Backbone.js模型。

<强> HTML:

<form action="/posts.js" method="post" data-remote="true" enctype="multipart/form-data">
  <input type="text" name="post[message]" />
  <input type="file" name="post[file]" />
  <button>Submit</button>
</form>

<强> JavaScript的:

您显然应该绑定ajax:error来处理错误情况。

对我来说,数据已在ActiveRecord模型中进行了清理,因此不必过于担心eval语句。

$('form').bind('ajax:success', function(event, data) {
  new Model(eval(data)); // Your newly created Backbone.js model
});

Rails控制器:

class PostsController < ApplicationController
  respond_to :js

  def create
    @post = Post.create(params[:post])
    respond_with @post
  end
end

Rails查看(create.js.haml):

使用remotipart gem。

这将处理表单执行文件上传时设置enctype的情况,以及未设置的情况。

您可以选择在此处为您的回复致电sanitize

= remotipart_response do
  - if remotipart_submitted?
    = "eval(#{Yajl::Encoder.encode(@post)});"
  - else
    =raw "eval(#{Yajl::Encoder.encode(@post)});"

答案 1 :(得分:3)

您可能需要查看jquery.iframe.transport插件。如果您正在使用rails 3,则可以使用remotipart代替它(它捆绑iframe.transport插件),该插件挂钩到rails的ujs驱动程序,以自动添加对ajax请求中文件上载的支持。

答案 2 :(得分:1)

恢复这一个。

如前面的答案中所述,可以通过jQuery.ajax执行多部分/表单数据请求:

var formData = new FormData();
var input = document.getElementById('file');

formData.append('file', input.files[0]);

$.ajax({
  url: 'path/to/upload/endpoint'
  type:'POST',
  data: formData,
  processData: false,
  contentType: false
});

同样重要的是要注意,开箱即用的Backbone.sync会通过model.save(null, { /* options here */ })将所有选项与$.ajax指令合并。

您的保存程序如下所示:

var model = new Model({
  key: 'value'
});
var input = document.getElementById('file');
var formData = new FormData();

_.each(model.keys(), function (key) { // Append your attributes
  formData.append(key, model.get(key));
});

formData.append('file', input.files[0]); // Append your file

model.save(null, {
  data: formData, 
  processData: false,
  contentType: false 
});

答案 3 :(得分:0)

我认为你误解了骨干的运作方式。 Backbone是javascript的MVC库,而不是Web服务器。文件上载在客户端浏览器和服务器之间协商。 Backbone只是中间层,可以帮助您轻松,方便地组织和呈现数据。

话虽这么说,将文件与模型关联起来需要做的是1)使用rails处理上传,然后2)将文件名和位置存储在模型中的字符串中。

所以这是文件上传部分:

  

http://khamsouk.souvanlasy.com/articles/ajax-file-uploads-in-rails-using-attachment_fu-and-responds_to_parent

返回list_item对象后,您只需在模型中创建一个新字段,然后存储list_item.filenameasset_path(list_item)

希望有所帮助。

答案 4 :(得分:0)

如果您不介意破坏向后兼容性,则可以利用XHR2 and FormData

这很简单:

var data = new FormData( $('form.someForm').get(0) );
$.ajax('http://*****.com', {
  type:'POST',
  data: data,
  processData: false,
  contentType: false // it automaticly sets multipart/form-data; boundary=...
});