2011-06-28 43 views
29

Tôi đang sử dụng Backbone.js trong ứng dụng Rails và tôi cần thực hiện tải lên tệp như là một phần của một trong các mô hình Backbone.Tải lên tệp bằng Backbone

Tôi không tin Backbone cho phép tải tệp đa phần ra khỏi hộp. Có ai quản lý để làm cho nó hoạt động thông qua một số plugin hoặc với một lib bên ngoài? Làm thế nào tôi có thể mở rộng Backbone.js để hỗ trợ điều này?

Trả lời

20

Trả lời câu hỏi của riêng tôi sau vài tháng dùng thử bằng các phương pháp khác nhau. Giải pháp của tôi là sau (với Rails).

Đối với bất kỳ biểu mẫu nào yêu cầu tải lên tệp, tôi sẽ đặt data-remote="true"enctype="multipart/form-data" và bao gồm rails.jsjquery.iframe-transport.js.

Đặt data-remote="true" với rails.js cho phép tôi liên kết với ajax:success và tạo mô hình Backbone.js thành công.

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:

Bạn rõ ràng nên ràng buộc ajax:error để xử lý các trường hợp lỗi.

Đối với tôi, dữ liệu được vệ sinh trong mô hình ActiveRecord, vì vậy đừng lo lắng quá nhiều về tuyên bố eval.

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

Rails Bộ điều khiển:

class PostsController < ApplicationController 
    respond_to :js 

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

Rails View (create.js.haml):

Sử dụng đá quý remotipart.

Thao tác này sẽ xử lý trường hợp tệp tải lên với biểu mẫu enctype và khi nào tệp đó không được đặt.

Bạn có thể chọn gọi sanitize về câu trả lời của mình tại đây.

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

Gọn gàng. Hai câu hỏi mặc dù. Trong bộ điều khiển của bạn, bạn có định làm 'Post.new (params [: post])' hay bạn thực sự có nghĩa là 'Post.create (params [: post])'? Và thứ hai, nơi bạn sẽ đặt '$ ('form'). Bind ('ajax: success')' gọi lại, trong một lớp Backbone.View cho biểu mẫu đã cho? Cảm ơn! –

+0

Bắt tuyệt vời, đánh máy về phía tôi. Nó phải là 'Post.create'. Tôi sẽ đặt $ ('form'). Bind ('ajax: success') trong khung nhìn Backbone của tôi để render form. –

+0

Thêm kiểu dữ liệu = "json" vào biểu mẫu và bạn có thể xóa chế độ xem. – maletor

0

Tôi nghĩ bạn hiểu lầm về cách hoạt động của xương sống. Backbone là một thư viện MVC cho javascript, không phải là một máy chủ web. Tải lên tệp được thương lượng giữa trình duyệt của khách hàng và máy chủ của bạn. Xương sống chỉ là lớp giữa giúp bạn sắp xếp và trình bày dữ liệu một cách dễ dàng, thuận tiện.

Điều đó đang được nói, những gì bạn cần làm để liên kết tệp với mô hình của bạn là 1) xử lý tải lên bằng đường ray rồi 2) lưu trữ tên tệp và vị trí trong chuỗi trong mô hình của bạn.

Vì vậy, đây là một phần tập tin tải lên:

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

Khi bạn lấy lại đối tượng list_item, bạn sẽ chỉ tạo ra một lĩnh vực mới trong mô hình của bạn và lưu trữ list_item.filenameasset_path(list_item).

Hy vọng điều đó sẽ hữu ích.

+0

Ngoài ra, đây là một liên kết đến một câu hỏi tương tự SO cho Django http://stackoverflow.com/questions/6092596/backbone-js-link-file -to-model – Swift

3

Bạn có thể muốn xem plugin jquery.iframe.transport. Nếu bạn đang sử dụng đường ray 3, bạn có thể sử dụng remotipart để thay thế (nó gói plugin iframe.transport), móc nối vào trình điều khiển ujs của đường ray để tự động thêm hỗ trợ tải lên tệp trong yêu cầu ajax.

+0

Cảm ơn Matt. Tôi đã kết thúc bằng cách sử dụng chính xác những gì bạn mô tả một lúc trở lại nhưng không nhận được xung quanh để cập nhật câu hỏi này. –

0

Nếu bạn không nhớ để phá vỡ tính tương thích ngược, bạn có thể tận dụng lợi thế của XHR2 and FormData

Đó là đơn giản như vậy:

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=... 
}); 
1

Đang phục hồi này.

Như đã đề cập trong câu trả lời trước, một yêu cầu multipart/form-data có thể được thực hiện thông qua 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 
}); 

Nó cũng quan trọng cần lưu ý rằng, out-of-the-box, Backbone.sync sẽ hợp nhất bất kỳ tùy chọn qua model.save(null, { /* options here */ }) với hướng dẫn $.ajax.

bạn tiết kiệm thủ tục sẽ giống như thế:

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 
});