ファイルシステムまたはデータベースのどちらに保存するかによって、二通りの方法に大別できます。
app/views/main/index.html.erb
<%= form_tag({action: :upload_process}, multipart: true) do %>
<%= file_field_tag :upfile %>
<%= submit_tag 'UPLOAD' %>
<% end %>
app/controllers/main_controller.rb
class MainController < ApplicationController
def index
end
def upload_process
file = params[:upfile]
fname = file.original_filename.encode('Shift_JIS') # Windowsの例
if not ['.png', '.jpg', '.jpeg', '.gif'].include?(File.extname(fname).downcase) then
res = 'error 1'
elsif file.size > 1.megabyte
res = 'error 2'
else
File.open("C:/Users/Public/#{fname}", 'wb'){|f| f.write(file.read)}
res = 'success'
end
render text: res
end
def show #「キャプチャ.PNG」というファイルを表示する例
# send_dataを利用する例:
# (変数をもとにレスポンスを生成)
f = File.open("C:/Users/Public/キャプチャ.PNG".encode('Shift_JIS'), 'rb')
send_data f.read, type: 'image/png', disposition: :inline
f.close
# send_fileを利用する例:
# (ファイルをもとにレスポンスを生成
# 「:inline」ブラウザに表示、「:attachment」ダウンロード(規定)
# send_file "C:/Users/Public/キャプチャ.PNG".encode('Shift_JIS'), type: 'image/png', disposition: :inline
# 参考:
# send_file "C:/path/to/file.zip"
# send_file "C:/path/to/file.pdf", filename: 'renamed.pdf'
end
end
app/views/main/index.html.erb
<%= form_for(@my_model, url: {action: :upload_process}, html: {multipart: true}) do |f| %>
<%= f.file_field :data %>
<%= f.submit 'UPLOAD' %>
<% end %>
app/controllers/main_controller.rb
class MainController < ApplicationController
def index
@my_model = MyModel.new
end
def upload_process
# ホワイトリストとして「data」の更新のみを許可
@my_model = MyModel.new(params.require(:my_model).permit(:data))
if @my_model.save then
render text: 'success'
else
render text: @my_model.errors.full_messages[0]
end
end
def show
@my_model = MyModel.find(params[:id])
send_data @my_model.field2, type: @my_model.field1, disposition: :inline
end
end
app/models/my_model.rb
class MyModel < ActiveRecord::Base
validate :ufile_valid?
# 擬似的にdataフィールドを定義 (内部ではfield1,field2を更新)
# rails generate scaffold myModel field1:string field2:binary
def data=(data)
self.field1 = data.content_type
self.field2 = data.read
end
private
def ufile_valid?
errors.add(:data, 'error 1') if not ['image/jpeg', 'image/gif', 'image/png'].include?(self.field1)
errors.add(:data, 'error 2') if self.field2.length > 1.megabyte
end
end