 |
|
레일스에서 파일 업로드하기(여기서는 XML)
이 XML 튜토리얼을 읽으면서 다소 흥분해 있는 여러분의 모습을 상상해 보자. 아마 튜토리얼을 쭉 따라 하면서 몇 번의 링크를 클릭해 XML 샘플 문서를 만들어냈을 것이다. 여러분은 흥분한 나머지 직접 만든 XML 파일을 상사에게 보여준다. 하지만 상사는 좀 실망스럽다는 반응을 보인다. 그는 특히 Fish Head Curry와 Pig Organ Soup에 굉장히 나쁜 평가가 매겨져 있다는 것에 대해 당황스러워한다. 여러분의 상사는 당신에게 즉시 웹 서비스를 하나 만들어서 자신이 좋아하는 요리에 원하는 평가를 직접 매긴 XML 문서를 업로드할 수 있게 해달라고 요구한다. 여러분은 운이 좋다. 왜냐하면 그것이 바로 이 튜토리얼의 나머지에서 다룰 내용들이니까! 이제 레일스를 사용해 파일을 어떻게 업로드하는지 살펴보자.
코드 보기
파일 업로드 폼(form)을 처리하는 뷰의 일부 코드를 빠르게 훑어보자(Listing 22).
Listing 22. XML 문서를 업로드하기 위한 RHTML 폼
<% form_tag( {:action => 'upload'}, {:multipart => true} ) do -%>
<p>
<label for="file">File:</label><%= file_field_tag "xml_file" %><br/>
<%= submit_tag "Parse with REXML" %>
<%= submit_tag "Parse with Hpricot" %>
</p>
<% end -%>
|
폼을 만들기 위해 레일스 프레임워크에 있는 표준 form_tag와 helper 메서드를 사용한다. 더불어 HTML 파일 입력 태그를 생성하는 file_field_tag와, HTML 제출(submit) 버튼을 생성하는 submit_tag도 사용한다. 업로드된 XML 문서의 파싱을 컨트롤러 내의 어느 핸들러가 담당할지 결정하기 위해 submit_tag의 값들을 사용한다. 그다지 우아해 보이진 않지만, 이 예제의 목적은 충분히 이룬다. 이 튜토리얼에서는 모델을 사용하지 않기 때문에 여기서도 모델을 기반으로 동작하기 위한 helper 태그는 사용하지 않는다.
컨트롤러 코드
레일스 컨트롤러에서 업로드된 파일의 내용을 얻으려면 코드 한 줄만 작성하면 된다(Listing 23).
Listing 23. 레일스 컨트롤러에서 인자(params) 객체로부터 업로드된 파일 가져오기
def upload
uploaded_file = params[:xml_file]
end
|
만약 사용자가 파일 입력 박스에서 파일을 업로드했다면 StringIO나 File의 인스턴스로 결과를 받는다. 만약 파일을 지정하지 않았다면, 업로드의 결과는 빈 String이 된다. 여러분은 사실 uploaded_file 객체의 클래스가 무엇인지 신경 쓸 필요가 없다. 단지 객체가 read 메서드에 대응하는지, 아닌지만 신경 쓰면 된다. uploaded_file 인스턴스가 read 메서드에 대응하는 경우에 한하여 파일 내용을 변수로 할당하는 코드를 작성할 수 있다(Listing 24).
Listing 24. 업로드된 파일의 내용을 String 변수로 읽어 들이기
def upload
uploaded_file = params[:xml_file]
data = uploaded_file.read if uploaded_file.respond_to? :read
end
|
이제 업로드된 데이터를 원하는 파서에 넘겨줄 수 있다. 여기서는 사용자가 브라우저에서 어떤 버튼을 클릭했는지에 따라 REXML과 Hpricot 둘 중 하나에 데이터를 전달하게 된다(Listing 25).
Listing 25. 사용자 입력에 따라 적당한 파싱 메서드로 위임하기(delegation)
def upload
uploaded_file = params[:xml_file]
data = uploaded_file.read if uploaded_file.respond_to? :read
if request.post? and data
case params[:commit]
when "Parse with REXML" : parse_with_rexml( data )
when "Parse with Hpricot" : parse_with_hpricot( data )
else parse_recursive( data )
end
else
redirect_to :action => 'index'
end
end
|
Listing 25에서 짚고 넘어갈 부분은 코드의 첫 번째 줄 밖에 없다. 첫 번째 if 문은 요청이 POST인지 확인하고 실제로 업로드된 데이터가 있는지 확인한다. 대충 이 정도다. 이제 업로드된 XML을 가지고 실제로 파싱하고 처리하기 위해 어떤 코드를 작성하면 되는지 알아보자.
|