37

複数のファイルをアップロードするフォームがあります。問題は、フォームを送信しているときに検証エラーが発生し、ファイル入力フィールドがリセットされることです。

私は基本的に、完全なプロセスのためにファイル入力フィールド内にこれらのファイルを保持したいと考えていました。

私もいくつかのリンクを通過しました

フォーム検証エラーでアップロードされた画像を「保持」するにはどうすればよいですか?

そのような場合に従うことができるさまざまなオプションを教えてください。

4

7 に答える 7

7

Carrierwave は、ファイルのアップロードを処理するための優れたツールであり、これを処理できます。

https://github.com/jnicklas/carrierwave#make-uploads-work-across-form-redisplays

于 2013-03-28T12:14:40.910 に答える
2

Rails で Paperclip を使用し、検証エラーが発生したときにファイルを維持する例を含むリポジトリを作成しました

https://github.com/mariohmol/paperclip-keeponvalidation

于 2015-01-21T22:43:07.913 に答える
1

Paperclip Gem を使用して最近のプロジェクトでこれを修正する必要がありました。少しハックですが、動作します。モデルで after_validation と before_save を使用して cache_images() を呼び出してみましたが、何らかの理由で作成に失敗したため、コントローラーから呼び出すだけです。うまくいけば、これは他の誰かの時間を節約します!

モデル:

class Shop < ActiveRecord::Base    
  attr_accessor :logo_cache

  has_attached_file :logo

  def cache_images
    if logo.staged?
      if invalid?
        FileUtils.cp(logo.queued_for_write[:original].path, logo.path(:original))
        @logo_cache = encrypt(logo.path(:original))
      end
    else
      if @logo_cache.present?
        File.open(decrypt(@logo_cache)) {|f| assign_attributes(logo: f)}
      end
    end
  end

  private

  def decrypt(data)
    return '' unless data.present?
    cipher = build_cipher(:decrypt, 'mypassword')
    cipher.update(Base64.urlsafe_decode64(data).unpack('m')[0]) + cipher.final
  end

  def encrypt(data)
    return '' unless data.present?
    cipher = build_cipher(:encrypt, 'mypassword')
    Base64.urlsafe_encode64([cipher.update(data) + cipher.final].pack('m'))
  end

  def build_cipher(type, password)
    cipher = OpenSSL::Cipher::Cipher.new('DES-EDE3-CBC').send(type)
    cipher.pkcs5_keyivgen(password)
    cipher
  end

end

コントローラ:

def create
  @shop = Shop.new(shop_params)
  @shop.user = current_user
  @shop.cache_images

  if @shop.save
    redirect_to account_path, notice: 'Shop created!'
  else
    render :new
  end
end

def update
  @shop = current_user.shop
  @shop.assign_attributes(shop_params)
  @shop.cache_images

  if @shop.save
    redirect_to account_path, notice: 'Shop updated.'
  else
    render :edit
  end
end

見る:

= f.file_field :logo
= f.hidden_field :logo_cache

- if @shop.logo.file?
  %img{src: @shop.logo.url, alt: ''}
于 2014-05-16T22:16:21.457 に答える
1

ええと、私はこれに対して別のアプローチを取ることを考えました。ファイルをサーバーに一時的に保存する代わりに、ユーザーが検証の問題を修正したときに再送信できるように、ファイルをクライアントに提供してみませんか。

これにはまだ少し改良が必要かもしれませんが、それが一般的な概念です。

# in the controller - save the file and its attributes to params

def create
  # ...
  if params[:doc] # a regular file uploaded through the file form element
    # when the form re-renders, it will have those additional params available to it
    params[:uploaded_file] = params[:doc].read # File contents
    params[:uploaded_file_original_filename] = params[:doc].original_filename
    params[:uploaded_file_headers] = params[:doc].headers
    params[:uploaded_file_content_type] = params[:doc].content_type
  elsif params[:uploaded_file] # a file coming through the form-resubmit
    # generate an ActionDispatch::Http::UploadedFile
    tempfile = Tempfile.new("#{params[:uploaded_file_original_filename]}-#{Time.now}")
    tempfile.binmode
    tempfile.write CGI.unescape(params[:uploaded_file]) #content of the file / unescaped
    tempfile.close

    # merge into the params
    params.merge!(doc: 
       ActionDispatch::Http::UploadedFile.new(
                                :tempfile => tempfile,
                                :filename => params[:uploaded_file_original_filename],
                                :head => params[:uploaded_file_headers],
                                :type => params[:uploaded_file_content_type]
                           )
                 )

  end
  #...
  # params (including the UploadedFile) can be used to generate and save the model object
end


# in the form (haml)
- if !params[:uploaded_file].blank?
  # file contents in hidden textarea element
  = text_area_tag(:uploaded_file, CGI.escape(params[:uploaded_file]), style: 'display: none;') #escape the file content
  = hidden_field_tag :uploaded_file_headers, params[:uploaded_file_headers]
  = hidden_field_tag :uploaded_file_content_type, params[:uploaded_file_content_type]
  = hidden_field_tag :uploaded_file_original_filename, params[:uploaded_file_original_filename]
于 2014-09-15T17:29:49.410 に答える
0

完全な解決策ではなく、これに対する回避策は、クライアント側の検証を使用して、フォーム全体が存続するためにファイルが失われないようにすることです。

JavaScript を有効にしていない少数のユーザーは、リクエスト間でファイルを失うことになりますが、おそらくこの % は非常に低いため、許容できる妥協点となります。これがあなたが下ることに決めたルートであるなら、私はこの宝石をお勧めします

https://github.com/bcardarella/client_side_validations

これにより、プロセス全体が非常にシンプルになり、JavaScript で検証を書き直す必要がなくなります。

于 2013-03-28T12:34:13.993 に答える