가장 간단한 파일업로드 폼

파일 업로드 폼을 보기 위해 home 컨트롤러에 index 액션을 생성한다.

$ rails g controller home index

그리고 home#index 액션을 루트 url로 지정하기 위해 config/routes.rb 파일을 열고 아래와 같이 추가한다.

root "home#index"

app/views/home/index.html.erb 파일을 열고 레일스에서 구현할 수 있는 가장 간단한 파일 업로드 폼을 아래와 같이 작성해 볼 수 있다.

<%= form_tag({action: :upload}, multipart: true) do %>
  <%= file_field_tag 'picture' %>
<% end %>

다음으로 위에서 폼 액션으로 지정한 :upload 액션을 home 컨트롤러에 추가(app/controllers/home/home_controller.rb)하고,

class HomeController < ApplicationController
  def index
  end

  def upload
  end
end

아래와 같이 라우팅(config/routes.rb)을 추가해 준다.

Rails.application.routes.draw do
  root 'home#index'
  post 'home/upload' => "home#upload", as: :upload
  ...

end

이제 정의한 라우팅이 제대로 작성되었는지를 아래의 명령으로 확인해 본다.

$ rake routes
Prefix Verb URI Pattern            Controller#Action
  root GET  /                      home#index
upload POST /home/upload(.:format) home#upload

위에서 form_tag 메소드에 multipart: true 옵션을 지정한 것을 파일업로드 위해 반드시 추가해 주어야 한다.

이제 서버를 실행한 후 브라우저에서 http://localhost:3000으로 연결할 때 아래와 같이 보이게 된다.

파일업로드 폼

파일선택 버튼을 클릭하여 파일을 선택하면

파일선택

아래와 같이 선택한 파일명이 버튼 옆에 보이게 된다.

파일선태후

이제 선택한 파일을 업로드하기 위해서 app/views/home/index.html.erb 파일을 다시 열고 아래와 같이 서밋 버튼을 폼에 추가한다.

<%= form_tag({action: :upload}, multipart: true) do %>
  <%= file_field_tag 'picture' %><br />
  <%= submit_tag %>
<% end %>

다시 업로드 파일을 선택한 후 아래와 같이 보이게 될 것이다.

이제 Save changes 버튼을 클릭하면 브라우저 창에 아래와 같은 에러가 쏟아지게 될 것이다.

이러한 에러의 원인은 app/views/home/ 디렉토리에 upload.html.erb라는 템플릿 파일이 존재하지 않기 때문이다. 따라서 해당 파일을 생성하고 아래와 같이 placeholder 문자를 추가하자.

<p>파일업로드 템플릿 파일!!!</p>

이제 다시 브라우저에서 http://localhost:3000 연결하여 새로운 파일을 업로드하고 Save changes 버튼을 클릭하면 아래와 같이 upload 액션에 대한 뷰 템플릿 파일이 보이게 되고,

웹서버 콘솔창에는 아래와 같은 결과가 보이게 된다.

우리는 여기서 파일 업로드시 서버로 요청되는 데이터 중 파라미터 값으로 사용할 수 있는 항목을 알 수 있다.

이 중에서도 "picture" 키 값으로 넘겨 받은 객체 값 중에는 서버에 임시로 저장된 업로드 파일의 위치가 있다.

실제 해당 위치에 가보면 이 파일에 존재하는 것을 확인할 수 있다. 이 외에도 파일명(original_filename), 파일형(content_type), 헤더값(headers)도 알 수 있게 된다.

다음은, 파일 업로드 후 렌더링 페이지에 이렇게 넘겨 받은 picture 키 값을 이미지와 함께 표시하도록 할 것이다.

app/controllers/home/home_controller.rb 파일을 열고 아래와 같이 코드를 추가한다.

class HomeController < ApplicationController
  def index
  end

  def upload
    uploaded = params[:picture]
    @original_filename, @content_type = file_save(uploaded)
  end

  private

  def file_save(uploaded_file)
    @original_filename = uploaded_file.original_filename
    @content_type = uploaded_file.content_type
    file = File.join("public", "images", @original_filename)
    FileUtils.cp uploaded_file.path, file
    FileUtils.rm uploaded_file.path
    return @original_filename, @content_type
  end

end

그리고, app/views/home/index.html.erb 파일을 열고 아래와 같이 추가한다.

<p>파일업로드 템플릿 파일!!!</p>

<ul>
  <li>파일명 : <%= @original_filename %></li>
  <li>파일형 : <%= @content_type %></li>
  <li><%= image_tag @original_filename %></li>
</ul>

이제 브라우저에서 페이지를 다시 로딩한 후 이미지 파일을 선택하여 Save changes 버튼을 클릭해 보자.

모델 객체와 연결하기 위한 또 다른 폼으로는 아래와 같이 구현할 수 있다.

<%= form_for @person do |f| %>
  <%= f.file_field :picture %>
<% end %>