Paperclip(3.0)和Rails(3.2):f.file_field在验证错误后丢失'new'操作的文件路径

Dar*_*rme 8 file-upload ruby-on-rails paperclip

我设置了一个story带有imagePaperclip处理的附件的模型,看起来像:

class Story < ActiveRecord::Base  
  has_attached_file :image # [...]
  attr_accessible :user_id, :title, :image, :image_file_name
  belongs_to: user

  validates_presence_of :user_id
  validates :title,     :length => { :maximum => 50 }
  validates_attachment_size :image, :less_than => 2.megabytes, :unless => Proc.new { |story| story[:image].nil? }
  # [...] 
end
Run Code Online (Sandbox Code Playgroud)

当我填写我的故事表格时,看起来像:

<%= form_for @story, html: { multipart: true } do |f| %>
<% if @story.errors.any? %>
<div id="error-explanation">
    <ul>
        <% @story.errors.full_messages.each do |msg| %>
        <li class="error-mess">Error: <%= msg.downcase %></li>
        <% end %>
    </ul>
</div>
<% end %>

<%= f.text_field :title %></td>
<%= f.file_field :image %>
<%= f.submit t('.send') %>

<% end %>
Run Code Online (Sandbox Code Playgroud)

如果一个story.title的验证失败太长,表单会正确地重新显示,并且正确的错误消息已填写的无效标题,file_field现在是空白的,我必须再次点击它才能重新选择文件我想上传.

以下是我的stories_controller.rb的样子:

def create
  @story = @current_user.stories.new(params[:story]) 
  if @story.save                                                                                                                   
    redirect_to thanks_path    
  else
    # !@story.save so I render action 'new' again just to
    # bang my head against this 'anomaly' 
    render action: "new"
  end              
end
Run Code Online (Sandbox Code Playgroud)

如何避免用户在验证错误后重新选择要上载的文件?

CBr*_*roe 5

HTTP文件上传的方式在浏览器中工作,该文件已经在首次提交时上传到您的应用程序 - 因此您应该将其存储在某个地方,以便您稍后在第二次表单提交时仍然可以访问它.(至少在PHP中,上传的文件在脚本运行后被删除,如果它没有被明确地移动到其他地方 - 我不知道这是否也适用于RoR.)

出于安全原因,您无法在HTML中预填充输入类型=文件字段.即使用户再次选择文件,他们也必须再次发送文件 - 浪费用户和带宽.

因此,要么在首次提交时将其存储在某个地方,要么在允许提交(尽可能)之前尝试使用JavaScript在客户端进行验证,以便最小化提交实际上在服务器端验证失败的表单.

  • 好的,现在的问题是:如何在RoR应用程序中检索上一个请求中上传的文件?:-)感谢您提供有关安全原因的提示,我并未完全了解这一点. (2认同)