上传多个图像时Rails回形针错误

时间:2014-03-13 21:02:50

标签: jquery ruby-on-rails ruby ruby-on-rails-4 paperclip

我使用jQuery文件上传,并有这样的形式:

= javascript_include_tag 'car_photos'
= stylesheet_link_tag('jquery.fileupload-ui')
= form_for @car do |f|
  .tab#car-data{style: "height: 1290px;"}
    .field
      = f.label :manufacturer_id, "Марка"
      = f.select(:manufacturer_id, options_from_collection_for_select(VehicleManufacturer.all, :id, :name, @car.manufacturer_id), {}, :prompt => "Выберите марку", required: true, id: "manufacturer-select")
    .field
      = f.label :model_id, "Модель"
      #models-area
        = render :partial => 'models', :object => @models
    .field
      = f.label :price, "Цена (рос.руб.)"
      = f.number_field :price, required: true, min: 0, step: 1, pattern: '[0-9]*', placeholder: "Например: 390000"
    .actions
      = link_to 'Перейти к загрузке фотографий', "", id: "go-and-load-photos", remote: true
  .tab#car-photo{style: "height: 1290px;"}
    .actions
      = link_to 'Назад к описанию', "", id: "go-and-load-car-data", remote: true
  .actions
    = f.submit 'Добавить', id: "submit-car"
.container
  = form_for CarPhoto.new, :html => { :multipart => true, :id => "fileupload", remote: true  } do |f|
    / The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload
    .row.fileupload-buttonbar
      .span7
        / The fileinput-button span is used to style the file input field as button
        %span.btn.btn-success.fileinput-button
          %i.icon-plus.icon-white
          %span Добавить файлы
          = f.file_field :car_photo, multiple: true
          = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
        %button.btn.btn-primary.start{type: "submit", remote: true}
          %i.icon-upload.icon-white
          %span Загрузить
        %button.btn.btn-warning.cancel{type: "reset", remote: true}
          %i.icon-ban-circle.icon-white
          %span Отменить загрузку
        %button.btn.btn-danger.delete{type: "button", remote: true}
          %i.icon-trash.icon-white
          %span Удалить
        %input.toggle{type: "checkbox"}/
      .span5
        / The global progress bar
        .progress.progress-success.progress-striped.active.fade
          .bar{style: "width:0%;"}
    / The loading indicator is shown during image processing
    .fileupload-loading
    %br/
    / The table listing the files available for upload/download
    %table.table.table-striped
      %tbody.files{"data-target" => "#modal-gallery", "data-toggle" => "modal-gallery"}
:javascript
  var fileUploadErrors = {
      maxFileSize: 'File is too big',
      minFileSize: 'File is too small',
      acceptFileTypes: 'Filetype not allowed',
      maxNumberOfFiles: 'Max number of files exceeded',
      uploadedBytes: 'Uploaded bytes exceed file size',
      emptyResult: 'Empty file upload result'
  };
/ The template to display files available for upload
%script#template-upload{type: "text/x-tmpl"}
  {% for (var i=0, file; file=o.files[i]; i++) { %}
  <tr class="template-upload fade">
  <td class="preview"><span class="fade"></span></td>
  <td class="name"><span>{%=file.name%}</span></td>
  <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
  {% if (file.error) { %}
  <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
  {% } else if (o.files.valid && !i) { %}
  <td>
  <div class="progress progress-success progress-striped active"><div class="bar" style="width:0%;"></div></div>
  </td>
  <td class="start">{% if (!o.options.autoUpload) { %}
  <button class="btn btn-primary">
  <i class="icon-upload icon-white"></i>
  <span>{%=locale.fileupload.start%}</span>
  </button>
  {% } %}</td>
  {% } else { %}
  <td colspan="2"></td>
  {% } %}
  <td class="cancel">{% if (!i) { %}
  <button class="btn btn-warning">
  <i class="icon-ban-circle icon-white"></i>
  <span>{%=locale.fileupload.cancel%}</span>
  </button>
  {% } %}</td>
  </tr>
  {% } %}
/ The template to display files available for download
%script#template-download{type: "text/x-tmpl"}
  {% for (var i=0, file; file=o.files[i]; i++) { %}
  <tr class="template-download fade">
  {% if (file.error) { %}
  <td></td>
  <td class="name"><span>{%=file.name%}</span></td>
  <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
  <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
  {% } else { %}
  <td class="preview">{% if (file.thumbnail_url) { %}
  <a href="{%=file.url%}" title="{%=file.name%}" rel="gallery" download="{%=file.name%}"><img src="{%=file.thumbnail_url%}"></a>
  {% } %}</td>
  <td class="name">
  <a href="{%=file.url%}" title="{%=file.name%}" rel="{%=file.thumbnail_url&&'gallery'%}" download="{%=file.name%}">{%=file.name%}</a>
  </td>
  <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
  <td colspan="2"></td>
  {% } %}
  <td class="delete">
  <button class="btn btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">
  <i class="icon-trash icon-white"></i>
  <span>{%=locale.fileupload.destroy%}</span>
  </button>
  <input type="checkbox" name="delete" value="1">
  </td>
  </tr>
  {% } %}
%script{charset: "utf-8", type: "text/javascript"}
  $(function () {
  \// Initialize the jQuery File Upload widget:
  $('#fileupload').fileupload();
  \//
  \// Load existing files:
  $.getJSON($('#fileupload').prop('action'), function (files) {
  var fu = $('#fileupload').data('fileupload'),
  template;
  fu._adjustMaxNumberOfFiles(-files.length);
  console.log(files);
  template = fu._renderDownload(files)
  \.appendTo($('#fileupload .files'));
  \// Force reflow:
  fu._reflow = fu._transition && template.length &&
  template[0].offsetWidth;
  template.addClass('in');
  $('#loading').remove();
  });

  });

和这样的控制器:

class CarPhotosController < ApplicationController
  before_action :set_car_photo, only: [:show, :edit, :update, :destroy]

  def new
    @car_photo = CarPhoto.new
  end

  def create 
    @car_photo = CarPhoto.new(car_photo_params) 
    #binding.pry
    respond_to do |format| 
      if @car_photo.save 
        format.html { redirect_to @car_photo, notice: 'Photo was successfully created.' } 
        format.json { data = {id: @car_photo.id, thumb: view_context.image_tag(@car_photo.car_photo.url(:thumb))} 
        render json: data, status: :created, location: @car_photo } 
      else 
        format.html { render action: "new" } 
        format.json { render json: @car_photo.errors, status: :unprocessable_entity } 
      end 
    end 
  end

  private
  # Use callbacks to share common setup or constraints between actions.
  def set_car_photo
    @car_photo = CarPhoto.find(params[:id])
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def car_photo_params
    params.require(:car_photo).permit(:car_photo, {:car_photo => []})
  end
end

当我尝试加载一些图像时,我得到:

Paperclip::AdapterRegistry::NoHandlerError in CarPhotosController#create

No handler found for [#<ActionDispatch::Http::UploadedFile:0x00000002d1af18 @tempfile=#<Tempfile:/tmp/RackMultipart20140313-3279-x4s5h2>, @original_filename="comment-it-hover.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"car_photo[car_photo][]\"; filename=\"comment-it-hover.png\"\r\nContent-Type: image/png\r\n">]

Extracted source (around line #9):

  def create 
    **@car_photo = CarPhoto.new(car_photo_params)** 
    #binding.pry
    respond_to do |format| 
      if @car_photo.save 
Request

Parameters:

{"utf8"=>"✓", "authenticity_token"=>"za/FgQrfxfn8SI3Ddbs1BtMptm67XOYgZBn+5QrvTiM=", "car_photo"=>{"car_photo"=>[#<ActionDispatch::Http::UploadedFile:0x00000002d1af18 @tempfile=#<Tempfile:/tmp/RackMultipart20140313-3279-x4s5h2>, @original_filename="comment-it-hover.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"car_photo[car_photo][]\"; filename=\"comment-it-hover.png\"\r\nContent-Type: image/png\r\n">]}}

但是有什么不对?如何解决这个错误?

如果我更改params.require(:car_photo).permit(:car_photo, {:car_photo => []}),则会收到不允许的错误。

2 个答案:

答案 0 :(得分:0)

CarPhotos模型中,您是否使用has_attached_file定义了附件。 对于Paperclip从4.0.0开始,您还需要具有文件名验证文件类型验证

答案 1 :(得分:0)

解决了这个问题:

@car_photo = CarPhoto.new(car_photo: car_photo_params[:car_photo].first) 

因为multiupload我需要注意数组......