我有一个受此railcast启发的多步骤表单,其中包含3个文件上传图像。但是,当我上传图片时,收到错误can't dump File
。
从SO中的其他问题我明白在会话中保存文件上传不起作用所以我需要使用这样的东西:
unless @post.valid?
@post.assets.first.attachment.clear
@post.assets.first.attachment.queued_for_write.clear
end
然而,这似乎不起作用。我应该查看三个文件上传并每次清除它们吗?如何避免此错误?
这是我的创建功能:
session[:post_params].deep_merge!(params[:post]) if params[:post]
session[:duration] = params[:post_duration] if params[:post_duration]
@post = Post.new(session[:post_params])
@post.current_step = session[:post_step]
unless @post.valid?
logger.info("attachment " + @post.assets.first.attachment.inspect)
@post.assets.first.attachment.clear
@post.assets.first.attachment.queued_for_write.clear
end
if @post.valid?
if params[:back_button]
@post.previous_step
elsif @post.last_step?
if @post.all_valid?
...
session[:post_step] = session[:post_params] = nil
redirect_to @post and return
end
else
@post.next_step
end
session[:post_step] = @post.current_step
end
if @post.new_record?
render "new"
end
end
我的资产模型
class Asset < ActiveRecord::Base
# attr_accessible :title, :body
belongs_to :post
attr_accessible :attachment
has_attached_file :attachment, :styles => { :medium => "600x600>", :small => "200x200>", :thumb => "100x100>" },
:default_url => "no_image_:style.jpg"
end
答案 0 :(得分:1)
问题是您无法将File
存储到会话对象中,因为它必须是Marshal
并且不受支持。在我看来,你有三种可能的解决方案:
简单的方法是在向导的最后一步添加图像上传部分。这样您就不需要在会话中保存最后一部分信息,而是直接保存在对象中。只需确保在最后一步中跳过会话保存,或者在将文件存储到会话之前取出文件参数
params[:post].except(:assets)
第二种解决方案比较棘手。您可以做的是每次控制器尝试保存模型时,您都会将附件保留在具有唯一名称的已知位置的磁盘上。现在,不是将文件存储到会话中,而是存储刚刚创建的本地文件名(您仍需要类似#1 中的except
以避免异常)。保存后,您将基本上从会话参数中指定的服务器磁盘还原文件。为了保持清洁,你需要一个能删除旧文件的cron作业(例如一周前保存的任何文件)。您可以使用whenever。
提示:如果您选择上述解决方案并且您的附件是一个单独的模型,就像看起来一样,您实际上可以保存“临时”资产而不需要关联的post_id
。然后,您将处理唯一的数据库ID,而不是文件名;)
最后,如果您的业务逻辑(和您的神经)允许它,您可以考虑在每个步骤中将模型保存在数据库中,可能带有一个标志意味着它已部分保存。这样你就不需要使用会话,但是你将不得不处理许多条件(在你的验证,你的范围,你的协会......)当然你还需要那个cron工作。