이미지와 같은 파일을 첨부하여 다른 페이지로 넘겨야 할 때가 있다. 그 때는 일반적인 방식으로 넘기면 file을 받을 수 없다.
주소창을 통해 전달하는 GET방식은 더 정확히 표현하면
주소창에 text형태로 파라미터를 넣어 전달한다.
text형식으로는 파일을 전송할 수 없다.
따라서 form에 파일을 전송하는 type이 하나라도 있다면 POST방식으로 전달해야 한다.
form의 기본 enctype(인코딩방식 설정)은
application/x-www.form-urlencoded로 되어있다.
이름에서 알 수 있듯이 url사용하여 전달하는데 이렇게 하면 파일명만 전달될 뿐이다.
form에 파일을 전송하는 type이 하나라도 있다면 enctype을 multipart/form-data로 꼭 설정해 주어야 한다.
multipart/form-data는 값을 분할하여 전송하고 받을 때 재조립하는 방식이다. 따라서 일반적인 파라미터로는 재조립을 할 수 없어 파일을 확인할 수 없다.
이 때 기존의 내장객체 request와 몇가지 옵션을 추가로 전달받아서 파일을 전송받을 수 있는 새로운 형태의 request를 생성하는 라이브러리 클래스가 필요하다
com.oreilly.servlet을 검색하여 나온 oreilly사이트에서
cos-22.05.zip을 다운로드 받는다
zip파일을 압축해제하여 lib폴더 안의 cos.jar를 사용하면 새로운 형태의 request를 만들 준비가 끝난다.
MultipartRequest 클래스 사용
new MultipartRequest (
request, savedirectory, maxPostSize, encoding, policy
// 기존request, 저징디렉토리, 최대전송크기, 글자인코딩, 중복처리정책
)
<form method="POST" enctype="multipart/form-data" action="ex01-action.jsp">
<input type="text" name="title" placeholder="제목">
<input type="file" name="image">
<input type="date" name="evenDate">
<!-- text,file,date 3가지 타입으로 데이터 넘기기 -->
<input type="submit">
</form>
BoardDTO의 멤버필드 (getter & setter도 준비한다!)
private String title;
private String image;
private Date eventDate;
이전에는 위와 같이 form이 있고 DTO가 그에 맞게 있다면
jsp:useBean을 사용하여 바로 DTO객체 생성 후 값을 넣을 수 있었다.
하지만 지금은 값을 분할하고 전송 후 재조립하기 때문에 위와 같은 방식을 사용할 수 없다.
지금부터 값을 받을 수 있는 새로운 request를 생성한 후 이를 통해 값을 넣은 DTO까지 반환하는 함수를 만들어보도록 하자.
private static FileUtil instance = new FileUtil();
public static FileUtil getInstance() { return instance; }
private FileUtil() {}
싱글톤을 생성하는 이유는 굳이 요청때마다 새로운 객체를 만들 필요 없이 같은 내용을 반복하기 때문에 만들어 준 것이다.
지금 싱글톤은 크게 중요한 부분이 아니다!
private String saveDirectory = null;
// saveDirectory는 jsp가 실행되어야 불러올 수 있으므로 일단 null로 설정한다
private String encoding = "UTF-8";
private int maxPostSize = 1024 * 1024 * 20; // 20MB
private FileRenamePolicy policy = new DefaultFileRenamePolicy();
public BoardDTO getDTO(HttpServletRequest request) throw Exception {
// 매개변수로 request를 전달받아 BoardDTO타입의 객체를 반환하는 함수
BoardDTO dto = null;
// 이 안의 내용을 이제부터 채워나갈 예정!!
return dto;
}
if(saveDirectory == null) {
ServletContext application
= request.getServletContext();
// 클라이언트가 요청한 context정보를 반환하는 메서드
saveDirectory = application.getRealPath("\upload");
// 파일을 저장할 공간의 경로를 '\upload'로 지정하겠다
File dir = new File(saveDirectory);
// ()안의 경로에 File객체 생성
dir.mkdirs();
// 상위 존재하지 않는 부모폴더까지 포함하여 해당 경로에 폴더만들기
}
MultipartRequest mpRequest = new MultipartRequest(
request, saveDirectory, maxPostSize, encoding, policy
);
// 이제 request 대신 mpRequest를 사용한다!
String title = mpRequest.getParameter("title");
// form의 input에 있는 name이었던 title을 ()안에 그대로 쓴다
File image = mpRequest.getFile("image");
String -> java.util.Date -> long -> java.sql.Date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// Date를 원하는 문자열 형식으로 변환
String inputDate = mpRequest.getparameter("evenDate");
java.util.Date d1 = sdf.parse(inputDate);
// 원하는 형식으로 바꾼 날짜를 d1에 저장
long time = d1.getTime();;
java.sql.Date d2 = new java.sql.Date(time);
dto = new BoardDTO();
dto.setTitle(title);
dto.setImage(image.getname());
// dto에 저장할 때에는 File명만 문자열 형식으로 저장한다!!
dto.setEvenDate(d2);
끝!!
<!-- ex01-action.jsp -->
<c:set var="fileUtil" value="${FileUtil.getInstance() }" />
<c:set var="dto" value="${fileUtil.getDTO(pageContext.request) }" />
<h3>title : ${dto.title }</h3>
<h3>imageName : ${dto.image }</h3>
<h3>eventDate : ${dto.eventDate }</h3>
<div>
<img src="upload/${dto.image }">
</div>
form에서 action으로 전송된 페이지를 위와 같이 작성해주면
File 및 다른 값들도 잘 받은 것을 확인 할 수 있다!
🔥 한줄평
File받는 것이 쉽지 않다는 것을 알았다....
File이 하나라도 섞여있으면 다른 값들까지 같이 복잡하게 처리해야 한다니...