Подтвердить что ты не робот

Загрузка файла с помощью базовой линии

Я использую Backbone.js в приложении Rails, и мне нужно делать загрузку файлов как часть одной из моделей Backbone.

Я не считаю, что Backbone позволяет загружать многокомпонентные файлы из коробки. Кто-нибудь смог заставить его работать через какой-либо плагин или с другой внешней библиотекой? Как я могу расширить Backbone.js для поддержки этого?

4b9b3361

Ответ 1

Отвечая на мой собственный вопрос после нескольких месяцев испытаний, используя разные методы. Мое решение следующее (с Rails).

Для любой формы, требующей загрузки файла, я бы установил data-remote="true" и enctype="multipart/form-data" и включил rails.js и jquery.iframe-transport.js.

Настройка data-remote="true" с помощью rails.js позволяет мне привязываться к 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 View (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)});"

Ответ 2

Вы можете проверить плагин jquery.iframe.transport. Если вы используете рельсы 3, вы можете вместо этого использовать remotipart (он связывает плагин iframe.transport), который подключается к рельсам ujs driver автоматически добавлять поддержку для загрузки файлов в запросы ajax.

Ответ 3

Я думаю, вы неправильно понимаете, как работает позвоночник. Backbone - это библиотека MVC для javascript, а не веб-сервер. Загрузка файлов согласовывается между браузером клиентов и вашим сервером. Магистраль - это только средний слой, который помогает вам легко и удобно организовывать и представлять данные.

При этом вам нужно связать файл с вашей моделью: 1) обработать загрузку с помощью рельсов, а затем 2) сохранить имя и местоположение файла в строке в вашей модели.

Итак, вот часть загрузки файла:

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

Как только вы вернете объект list_item, вы просто создадите новое поле в своей модели и сохраните list_item.filename и asset_path(list_item).

Надеюсь, что это поможет.

Ответ 4

Если вы не возражаете отказаться от обратной совместимости, вы можете воспользоваться XHR2 и 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=...
});

Ответ 5

Возобновление этого.

Как упоминалось в предыдущих ответах, запрос multipart/form-data может быть выполнен с помощью 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 
});