Web Spring 자료실
자료실 구현
1. pom.xml 에 업로드사용할 라이브러리 추가
<!-- 파일 업로드 (자료실) -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
2. servlet-context 에서 업로드와 다운로드시 필요한 클래스(객체) 인스턴스 생성
<!-- upload -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="104857600"/>
<property name="maxInMemorySize" value="102400"/>
<property name="defaultEncoding" value="utf-8"/>
<property name="uploadTempDir" value="upload"/> <!--서버에 업로드할 폴더명 -->
</bean>
<!--download -->
<bean id="downloadView" class="bit.com.spring.util.DownloadView"/>
<bean id="downloadViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order">
<value>0</value>
</property>
</bean>
3. util쪽에서 업로드와 다운로드시 필요한 파일 이름변경 위한 메소드 생성
package bit.com.spring.util;
import java.util.Date;
//파일명 중복에 대한 방지를 위한 util
public class PdsUtil {
//ex: myfile.txt -> f.indexOf('.') -> 0부터 6까지 온다
//파일명, 확장자명
//f.substring(6) => .txt 를 가져온다
//f.substring(0,6) => myfile 을 가져온다
//myfile.txt -> 23423232323.txt 로 저장 할것이다(앞에 숫자는 시스템시간)(충돌이 나지 않는다)
//oldfilename에는 myfile.txt 를 저장하고 filename 에는 23423232323.txt를 저장한다
public static String getNewFileName(String f) {
String filename = "";
String fpost = ""; //파일 확장자명
if(f.indexOf('.') >=0 ) { //확장자명이 있음
fpost = f.substring(f.indexOf('.')); // fpost = .txt가 들어가있다
filename = new Date().getTime() + fpost; // 32423423.txt로 들어가게 된다
}
else {
filename = new Date().getTime() + ".back"; //인위적으로 붙여준다
}
return filename;
}
}
4. 자료실 목록 표현, 디테일은 springsampleAll을 참고
- 아래 다룰 내용은 업로드와 다운로드시 컨트롤에서 어떻게 구현하는지 확인 (db는 파일의 이름만을 저장하는 용도)
5. 업로드 controller
@RequestMapping(value = "pdsupload.do",method = {RequestMethod.GET,RequestMethod.POST })
public String pdsupload(PdsDto pdsdto,
@RequestParam(value="fileload",required=false)MultipartFile fileload,HttpServletRequest req) { //@RequestParam 뒤에 는 파일 정보를 byte형식으로 받아주는 식
//filename 취득
String filename = fileload.getOriginalFilename(); //원본 파일 명 myfile.text 에서 myfile
pdsdto.setOldfilename(filename);
//upload 경로 설정
// 서버 톰캣에 올리는 경로 (서버가 껐다가 킬때 자주할 경우 데이터가 날라 갈 수 있다)
String fupload = req.getServletContext().getRealPath("/upload");
//폴더로 경로(데이터가 날아가지 않는다)
// String fupload = "d:\\tmp"; 클라이언트 로컬에 저장
System.out.println("fupload: "+fupload);
//file 명을 취득
String f = pdsdto.getOldfilename();
String newfilename = PdsUtil.getNewFileName(f); //return을 받게 되면 시스템 타임으로 파일명으로 받아온다
pdsdto.setFilename(newfilename); //바뀐 파일명을 dto에 set 시켜준다
//import java.io.File;
File file = new File(fupload+"/"+newfilename);
//파일을 만든다.(실제 업로드가 되는 부분) import org.apache.commons.io.FileUtils;
try {
FileUtils.writeByteArrayToFile(file, fileload.getBytes()); //fileload는 multipart에서 받아온것
//db 에 저장
service.uploadPds(pdsdto);
} catch (IOException e) {
e.printStackTrace();
}
return "redirect:/pdslist.do";
}
6. view에서 post로 넘겨준다 (form으로 post로 묶어서 넘겨준다)
- input 타입의 file은 post로 넘겨주어야 하며 multipart를 사용해주어야한다.
- 따라서 form의 설정에 몇가지 사항을 추가해 주어야 한다
<form name="frmForm" id="_frmForm" action="pdsupload.do" method="post" enctype="multipart/form-data">
다운로드
7. 우선 다운로드를 위해 util에 임시 뷰를 생성한다
package bit.com.spring.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;
import bit.com.spring.service.PdsService;
//web에서 등록을 해야하기 때문에 생성
// 가상 뷰 다운로드 창이 만들어지는곳
public class DownloadView extends AbstractView{
@Autowired
PdsService service;
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
System.out.println("DownloadView renderMergedOutputModel");
File file = (File)model.get("downloadFile"); //getAttribute랑 동일하다
response.setContentType(this.getContentType());
response.setContentLength((int)file.length());
//만약 IE/chrome
String userAgent = request.getHeader("user-Agent"); //브라우저 헤더부분에 MSIE가 -1 보다 크면 크롬이거나 다른 브라우져이다
boolean ie = userAgent.indexOf("MSIE") > -1;
String filename = null;
if(ie) {
filename = URLEncoder.encode(file.getName(), "utf-8");
}
else {
filename = new String(file.getName().getBytes("utf-8"),"iso-8859-1");
}
// 다운로드 창
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\";"); //파일명이 나오기 위해
response.setHeader("Content-Transfer-Encoding", "binary;");
response.setHeader("Content-Length", "" + file.length());
response.setHeader("Pragma", "no-cache;");
response.setHeader("Expires", "-1;");
OutputStream out = response.getOutputStream();
FileInputStream fi = null;
fi = new FileInputStream(file);
FileCopyUtils.copy(fi, out);
//download count 증가
if(fi != null) {
fi.close();
}
}
}
8. 다운로드 컨트롤러
//fileDownload.do
@RequestMapping(value = "fileDownload.do",method = {RequestMethod.GET,RequestMethod.POST })
public String fileDownload(String filename, int seq, HttpServletRequest req, Model model) {
//경로
//server
String fupload = req.getServletContext().getRealPath("/upload");
//폴더
// String fupload = "c:\\tmp"; 만약 로컬로 하게된다면
File downloadFile = new File(fupload + "/" + filename);
model.addAttribute("downloadFile", downloadFile);
model.addAttribute("seq", seq);
return "downloadView"; //servlet context 에서 id가 downloadView으로 생성하였던 인스턴스를 찾아간다.
}