纸夹异常:Paperclip :: AdapterRegistry :: NoHandlerError

44

我在Rails 3.2.2中使用Paperclip 3.0.1时遇到了这个错误:

**Paperclip::AdapterRegistry::NoHandlerError** 
(No handler found for "2009-11-29-133527.jpg"):

我的模型中有:

class Product < ActiveRecord::Base
    ...
    has_many :assets 
    accepts_nested_attributes_for :assets
 end

 class Asset < ActiveRecord::Base
     belongs_to :product
     has_attached_file :image,
               :path => ":rails_root/public/system/:attachment/:id/:style/:filename",
               :url => "/system/:attachment/:id/:style/:filename", 
               :styles => { :medium => "300x300>", :thumb => "100x100>" }
  end

异常发生在:

def create
     **@product = Product.new params[:product]**
     ...
end

带有参数:

{...,
 "product"=>{"title"=>"wibble1", 
             **"assets_attributes"=>{"0"=>{"image"=>"2009-11-29-133527.jpg"}
                                  },** 
             "description"=>"Who is wibble...", 
             "price"=>"23.45"
            }, 
             "commit"=>"Create Product", 
             ...}

有人知道发生了什么吗?

11个回答

50

出现此错误是因为您没有向Paperclip提供正确的类。它只是一个字符串。

您应该在params中收到类似于以下内容的东西。

"asset"=>
  {"image"=>
    #<ActionDispatch::Http::UploadedFile:0x000000056679e8
    @content_type="image/jpg",
    @headers= "Content-Disposition: form-data; name=\"asset[image]\";
      filename=\"2009-11-29-133527.jpg\"\r\nContent-Type: image/jpg\r\n",
    @original_filename=""2009-11-29-133527.jpg"",
    @tempfile=#<File:/tmp/RackMultipart20120619-1043-yvc9ox>>}

您应该在您的视图中拥有类似这样的内容(使用HAML,非常简化):

= form_for @product, html: { multipart: true } do |f|
  = f.fields_for :asset do |asset_form|
    = asset_form.file_field :image

记得将表单设置为 multipart: true


2
是的,请记得设置多部分选项。 例如:<%= form_for @video,:method =>:put,:html => {:multipart => true} do %> - Americo Savinon
1
在form_tag的情况下,应该是form_tag path, :multipart => true而不是使用:html关键字。链接 - bartolo-otrit
如果我从资源中选择图像呢? - Imran Ahmad
@Imran,你是怎么选择它的?听起来这似乎是一个不同的问题。 - Mauricio Pasquier Juan

30

我自己遇到了这个问题。在我的情况下,它是由于在标记中跳过了多部分表单声明引起的。

我正在使用formtastic,因此我添加了以下内容并使其工作:

semantic_form_for @picture, :html => {:multipart => true} do |f|


5
如果您正在使用form_for并在builder之外添加字段,则必须手动强制form_for成为多部分表单,通过 :html => {:multipart => true} 如上所示。仅仅添加 :multipart => true 不像form_tag那样起作用。 - agmin
这个答案对我有用!希望提问者能接受这个答案。通常情况下,当您为模型创建表单,最终会有嵌套属性的子对象接受文件附件,这在我的情况下就是这种情况。(在此分享我的经历,以供未来的谷歌搜索者参考) - Seth Malaki

5

注意,使用HTML5画布时有一种情况值得注意。将画布数据作为DataURI字符串获取并发送到服务器可能会导致此错误。Canvas .toDataURL()将给出类似于“data:image/png;base64,iVBORw0KGg...”的内容,您可以将其与其他信息一起发送到服务器,因此它不同于标准的多部分表单上传。如果您只将其设置为图钉附件字段,则会收到此错误。您需要将其转换为文件或IO对象。您可以像这样编写一个临时文件:

data_uri = params[:canvasDataUri]
encoded_image = data_uri.split(",")[1]
decoded_image = Base64.decode64(encoded_image)
File.open("signature.png", "wb") { |f| f.write(decoded_image) }

或者使用Ruby的StringIO,它的作用类似于内存文件接口。
@docHolder.document = StringIO.new(decoded_image)

希望这能帮助到您。

2

我的问题是在路由中不接受GET方法,所以我将其更改为PATCH方法,然后它就可以正常工作了。

<%= form_for @product, :url => "/products/#{@product.id}/upload",:method => :patch, :html => { :multipart => true } do |f| %>

2

我在文件输入中使用了<input type="file" ... multiple="multiple">,因此paperclip附件数据是一个数组。

我通过删除文件输入上的multiple属性来简单解决了这个问题。


2
这也是我的问题。我喜欢使用:multiple => true的便利性,但正如你所说,它会将名称设置为upload[upload][]。然而,我真的很喜欢多文件选择的便捷性,所以我只需手动设置名称,使其不成为数组,例如:name => 'upload[upload]' - Matthew Clark
我使用JavaScript和jQuery文件上传一起添加多个。 - Mirko
哈!将近三年后,我在另一个项目中遇到了完全相同的问题,和以前一样,这个答案和我的评论解决了我的问题。 - Matthew Clark

1
在我的情况下,我正在传递字符串,就像@MauricioPasquierJuan的答案一样,但我没有使用表单,所以答案的其余部分不适用。
我找不到任何有关如何以编程方式更新附件的文档 - 可以分配哪些类型以及为什么分配并保存修改后的记录不会保存修改后的附件。 这个问题是我发现的最接近的东西。
在处理上传的zip文件内部函数中处理文件后,将提取的文件保存到临时文件中,这是我的解决方案:
record.attachment = File.new( tempfile_path_as_string ) ## probably not the only option
record.attachment.save                                  ## next line doesn't update attachment without this
record.save

1
我相信你的问题与视图中的form_for有关, 尝试像这样做:
<%= form_for @restaurante, :html => { :multipart => true } do |form| %>
   Nome:<%= form.text_field :nome%>
   Endereço:<%= form.text_field :endereco %>
   Especialidade:<%= form.text_field :especialidade %>
   Foto:<%= form.file_field :foto %>
   <%= form.submit 'create'%>
<% end %>

0

对我来说,问题是这样的:

在控制器中,我使用了一行代码,因为在某些答案中看到了它:

@image = User.find(params[:id]).image.<b>path</b>(:small)

我遇到了“文件没有处理程序”的问题。

所以,我只是删除了“路径”,然后它就可以工作了:

@image = User.find(params[:id]).image(:small)

0
确保在安装Paperclip后迁移数据库('rake db:migrate')...此外,您可能需要将Paperclip生成的新数据字段添加到模型中的“attr_accessible”行中。当我尝试在我的一个项目上让Paperclip工作时,我遇到了类似的问题。

不幸的是,这对我并没有解决问题。添加attr_accessible :title,:description,:price,:assets_attributes仍然存在同样的问题。 - Sten Ka Razin

0

我遇到了同样的问题,我认为是因为有两个表共享相同的attached_file_name...在我的情况下,我为活动和推文都添加了一个:photo列,那么问题似乎是系统可以找到其中一个但找不到另一个。因为文件保存在/public/photo/:id/:id路径中,如果你有两列都命名为photo,那么问题就会出现。


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