Google App Engine(이하 GAE)의 spin up time 문제도 해결했기 때문에 주말 동안 탄력을 받아 그 동안 미뤄두고 있었던 이미지와 파일 업로드가 가능하도록 구현하기 위한 작업을 시작했다.
처음에는 Blobstore Java API Overview 문서를 참고해 GAE의 BlobStoreService API를 활용하는 방법으로 접근했다. 이 문서에서 제공하는 샘플 예제를 활용해 테스트도 해보니 생각보다 쉽게 해결할 수 있었다. 그런데 BlobStoreService API를 활용할 경우 업로드한 파일의 메타 정보를 알 방법이 없었다. 이 때는 BlobStoreService 에 대하여 잘 모르는 상태였기 때문에 이 같은 판단을 했다. 다음 글에서 BlobStoreService API를 활용해 업로드한 파일의 메타 정보를 추출하는 방법을 방법에 대하여 살펴보도록 하겠다 .
그래서 GAE에서 이미지, 파일을 업로드하기 위한 새로운 방법이 없는지 찾던 중 GAE의 DataStore에 Blob Type을 제공하고 있으며, GAE의 파일 업로드를 Spring MVC에서 파일을 업로드할 때와 같은 방법으로 개발이 가능하도록 지원하는 gmultipart라는 라이브러리가 존재하는 것을 확인하고 적용하기 시작했다. 사실 gmultipart 라이브러리는 더 이상 추가적인 개발이 되지 않고 있는 상황이라 찜찜했지만 일단 GAE의 Blob Type 활용이 가능한지를 검토하기 위해 이
기반으로 개발을 시작했다.
gmultipart 라이브러리를 활용한 샘플 예제는 gmultipart에 올라와 있는 예제를 그대로 활용했다. 일단은 테스트하는 것이 목적이었기 때문에 최대한 단순하게 테스트를 진행했다.
[... 중간 생략 ...] import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; import com.google.appengine.api.datastore.Blob; @Controller public class FileController { @Autowired private AttachedFileDao attachedFileDao; @RequestMapping(value = "/save", method = RequestMethod.POST) public String addComment(CommentForm commentForm) throws IOException { MultipartFile[] files = commentForm.getFiles(); AttachedFile attachedFile = null; MultipartFile file = files[0]; Blob attachment = new Blob(file.getBytes()); attachedFile = new AttachedFile(ServiceType.diaries, 1L, file.getOriginalFilename(), file.getSize(), attachment, DateTimeUtils.now()); attachedFileDao.put(attachedFile); return "redirect:/show/file/" + attachedFile.getId(); } }
위 예제에서 볼 수 있는 바와 같이 gmultipart
api를 활용할 경우 지금까지 Spring 프레임워크에서 사용하던 방법과 같이 Multipart를 활용해 업로드한 파일 정보를
추출하는 것이 가능하다.
import java.util.Date; import javax.persistence.Entity; import javax.persistence.Id; import com.google.appengine.api.datastore.Blob; import com.googlecode.objectify.annotation.Unindexed; @Entity public class AttachedFile { @Id private Long id; private ServiceType serviceType; private Long contentsId; @Unindexed private String originalFileName; @Unindexed private Long size; @Unindexed private Blob attachment; private Date createdDate; public AttachedFile() { } public AttachedFile(ServiceType serviceType, Long contentsId, String originalFileName, Long size, Blob attachment, Date createdDate) { this.serviceType = serviceType; this.contentsId = contentsId; this.originalFileName = originalFileName; this.size = size; this.attachment = attachment; this.createdDate = createdDate; } [... 중간 생략 ...] }
이와 같이 업로드한 파일 데이터는 DataStore의 Blob Type을 활용해 저장하는 것이 가능하다. 위 AttachedFile은 Objectify 프레임워크를 활용해 GAE의 DataSource에 저장하기 위한 모델 클래스이다.
단 GAE DataStore의 Blob Type은 1MB의 데이터까지만 저장할 수 있다는 한계가 있다. 1MB 이상의 파일을 저장하고 싶다면 BlobStoreService를 활용해야 한다. BlobStoreService를 활용하는 방법은 다음 문서에서 다루도록 하겠다.