Error rendering WebPanel: No renderer found for resource type: velocity Template contents: <meta name="ajs-keyboardshortcut-hash" content="$keyboardShortcutManager.shortcutsHash">

버전 비교

  • 이 줄이 추가되었습니다.
  • 이 줄이 삭제되었습니다.
  • 서식이 변경되었습니다.
댓글: Migration of unmigrated content due to installation of a new plugin

Five cool things you can do with Play 문서를 보면 play framework을 사용할 때 쉽게 구현할 수 있는 다섯가지 기능에 대하여 설명하고 있다. 이 다섯 가지 중의 하나가 파일 업로드를 얼마나 쉽게 구현할 수 있는지 설명하고 있다.

html form

코드 블럭
#{form @uploadPhoto(), enctype:'multipart/form-data'}
    <input type="text" name="title" />
    <input type="file" id="photo" name="photo" />
    <input type="submit" value="Send it..." />
#{/form}

controller code

코드 블럭
public static void uploadPhoto(String title, File photo) {
   ...
}

그런데 Google App Engine에서 위와 같이 구현할 경우 에러가 발생한다. 에러가 발생하는 이유는 Google App Engine이 로컬 파일 시스템에 접근할 수 없기 때문에 위 소스 코드와 같이 File Type을 사용할 수 없기 때문이다. File Type은 로컬 파일 시스템에 접근이 가능한 상태에서 사용할 수 있는 API이다. GAE에서는 이 같은 문제를 해결하려면 HttpServletRequest로 전달되는 스트림을 읽어서 메모리에서 처리가 가능하도록 구현해야 한다.

이와 관련한 해결책을 찾기 위해 온라인상에서 검색한 결과 다양한 해결 방법을 찾을 수 있었지만 딱히 좋은 해결 방법은 없었다. 온라인 상에서 찾은 문서는 다음과 같다.

이 이외에도 다양한 문서들을 찾았지만 딱히 마음에 드는 방법을 찾을 수 없었다. 문서를 이리 저리 찾다보니 Play에서 Upload라는 타입을 제공하고 있다는 것을 알게 되었다. 혹시나 하는 마음으로 File Type 대신 Upload Type을 다음과 같이 적용했다.

코드 블럭
import play.data.Upload;
 
[...]
 
public static void upload(Long id, Upload file) {
  Blob attachFile = new Blob(file.asBytes());
  AttachedFile attachedFile = new AttachedFile
      (ServiceType.diaries, id, file.getFileName(), file.getSize(), 
      file.getContentType(), attachFile);
  attachedFile.insert();
}

위 소스코드와 같이 Play에서 제공하는 Upload Type을 활용해 데이터 바인딩을 했더니 정상적으로 파일 업로드가 가능한 것을 확인할 수 있었다. 혹시라도 Google App Engine에서 Play Framework을 활용해 파일 업로드 기능을 구현하고자 한다면 Upload Type을 활용해 쉽게 구현이 가능하다.