diff --git a/src/main/java/cokr/xit/base/file/Downloadable.java b/src/main/java/cokr/xit/base/file/Downloadable.java deleted file mode 100644 index ed127ed..0000000 --- a/src/main/java/cokr/xit/base/file/Downloadable.java +++ /dev/null @@ -1,145 +0,0 @@ -package cokr.xit.base.file; - -import java.io.File; -import java.io.InputStream; -import java.net.URLConnection; - -import cokr.xit.foundation.Assert; - -public class Downloadable { - private Object file; - private String - charset, - filename, - contentType, - disposition; - private Number length; - - /**파일을 반환한다. - * @return 파일 - */ - public Object getFile() { - return file; - } - - /**파일을 설정한다. - * @param file 파일 - * @return 현재 Downloadable - */ - public Downloadable setFile(Object file) { - this.file = file; - return this; - } - - /**문자셋을 반환한다. - * @return 문자셋 - */ - public String getCharset() { - return Assert.ifEmpty(charset, "UTF-8"); - } - - /**문자셋을 설정한다. - * @param charset 문자셋 - * @return 현재 Downloadable - */ - public Downloadable setCharset(String charset) { - this.charset = charset; - return this; - } - - /**파일이름을 반환한다. - * @return 파일이름 - */ - public String getFilename() { - if (Assert.isEmpty(filename)) { - if (file instanceof File) - filename = ((File)file).getName(); - if (file instanceof FileInfo) - filename = ((FileInfo)file).getName(); - } - return Assert.notEmpty(filename, "filename"); - } - - /**파일이름을 설정한다. - * @param filename 파일이름 - * @return 현재 Downloadable - */ - public Downloadable setFilename(String filename) { - this.filename = filename; - return this; - } - - /**contentType을 반환한다. - * @return contentType - */ - public String getContentType() { - if (Assert.isEmpty(contentType)) - try { - if (file instanceof InputStream) { - InputStream input = (InputStream)file; - contentType = URLConnection.guessContentTypeFromStream(input); - } - if (file instanceof File) { - File file = (File)this.file; - contentType = URLConnection.guessContentTypeFromName(file.getName()); - } - if (file instanceof FileInfo) { - FileInfo fileInfo = (FileInfo)file; - contentType = fileInfo.getMimeType(); - } - } catch (Exception e) { - throw Assert.runtimeException(e); - } - - return Assert.ifEmpty(contentType, "application/octet-stream"); - } - - /**contentType을 설정한다. - * @param contentType contentType - * @return 현재 Downloadable - */ - public Downloadable setContentType(String contentType) { - this.contentType = contentType; - return this; - } - - /**disposition을 반환한다. - * @return disposition - */ - public String getDisposition() { - return Assert.ifEmpty(disposition, "attachment"); - } - - /**disposition을 설정한다. - * @param disposition disposition - * @return 현재 Downloadable - */ - public Downloadable setDisposition(String disposition) { - this.disposition = disposition; - return this; - } - - /**파일길이를 반환한다. - * @return 파일길이 - */ - public Number getLength() { - if (file instanceof File) { - File file = (File)this.file; - length = file.length(); - } - if (file instanceof FileInfo) { - FileInfo fileInfo = (FileInfo)this.file; - length = fileInfo.getSize(); - } - return length; - } - - /**파일길이를 설정한다. - * @param length 파일길이 - * @return 현재 Downloadable - */ - public Downloadable setLength(Number length) { - this.length = length; - return this; - } -} \ No newline at end of file diff --git a/src/main/java/cokr/xit/base/file/web/DownloadView.java b/src/main/java/cokr/xit/base/file/web/DownloadView.java index ba2743d..dde098d 100644 --- a/src/main/java/cokr/xit/base/file/web/DownloadView.java +++ b/src/main/java/cokr/xit/base/file/web/DownloadView.java @@ -10,11 +10,11 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.springframework.util.FileCopyUtils; import org.springframework.web.servlet.view.AbstractView; import cokr.xit.base.file.FileInfo; import cokr.xit.foundation.Assert; +import cokr.xit.foundation.Downloadable; /**파일의 다운로드를 처리하기 위한 {@link org.springframework.web.servlet.View} *

DownloadView가 파일을 다운로드하기 위해서는 {@link org.springframework.web.servlet.ModelAndView}로 다음과 같은 속성의 값을 지정해야 한다. @@ -30,6 +30,11 @@ import cokr.xit.foundation.Assert; public class DownloadView extends AbstractView { @Override protected void renderMergedOutputModel(Map model, HttpServletRequest hreq, HttpServletResponse hresp) throws Exception { + if (model.containsKey("download")) { + render((Downloadable)model.get("download"), hresp); + return; + + } InputStream input = getInputStream(model); if (input == null) { hresp.setStatus(HttpServletResponse.SC_NOT_FOUND); @@ -56,7 +61,7 @@ public class DownloadView extends AbstractView { if (length != null) hresp.setContentLengthLong(length.longValue()); - FileCopyUtils.copy(stream, hresp.getOutputStream()); + stream.transferTo(hresp.getOutputStream()); } finally { clear(model); } @@ -148,4 +153,25 @@ public class DownloadView extends AbstractView { if (file.exists()) file.delete(); } + + protected void render(Downloadable downloadable, HttpServletResponse hresp) throws Exception { + if (downloadable == null) { + hresp.setStatus(HttpServletResponse.SC_NOT_FOUND); + hresp.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + String filename = downloadable.getFilename(); + if (Assert.isEmpty(filename)) + throw new IllegalArgumentException("Unable to determine the filename"); + + String charset = downloadable.getCharset(); + hresp.setCharacterEncoding(charset); + hresp.setContentType(downloadable.getContentType()); + hresp.setHeader("Content-Disposition", downloadable.getDisposition() + "; filename=\"" + URLEncoder.encode(filename, charset) +"\""); + Long length = downloadable.getLength(); + if (length != null) + hresp.setContentLengthLong(length.longValue()); + + downloadable.write(hresp.getOutputStream()); + } } \ No newline at end of file diff --git a/src/main/java/cokr/xit/base/file/web/FileInfoFactory.java b/src/main/java/cokr/xit/base/file/web/FileInfoFactory.java index 83c4267..2c1c378 100644 --- a/src/main/java/cokr/xit/base/file/web/FileInfoFactory.java +++ b/src/main/java/cokr/xit/base/file/web/FileInfoFactory.java @@ -7,11 +7,20 @@ import java.util.List; import org.springframework.web.multipart.MultipartFile; import cokr.xit.base.file.FileInfo; +import cokr.xit.foundation.Downloadable; /**파일 정보 생성자 * @author mjkhan */ public class FileInfoFactory extends FileInfo.Factory { + public static Downloadable getDownloadable(FileInfo fileInfo) { + return new Downloadable() + .setFilename(fileInfo.getName()) + .setContentType(fileInfo.getMimeType()) + .setLength(fileInfo.getSize()) + .setWriter(fileInfo::write); + } + /**주어진 관계 정보 유형과 키, 그리고 업로드 파일로 FileInfo 목록을 생성한다. * @param relation 관계 정보 * @param multipartFiles 업로드 파일