<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>file-io</title>
</head>
<body>
<h1>File upload</h1>
<h4>commons fileupload를 이용하면 multiple도 가능하며,
파일을 여러 input 태그로 업로드 하는 것도 가능하다.</h4>
<form action="commons/fileupload" method="post" encType="multipart/form-data">
<input type="file" name="uploadfile" multiple><br>
<input type="text" name="description">
<button type="submit">전송</button>
</form>
</body>
</html>
@WebServlet("/commons/fileupload")
public class CommonsFileUploadServlet extends HttpServlet {
private String rootLocation;
private int maxFileSize;
private String encodingType;
@Override
public void init() {
ServletContext context = getServletContext();
rootLocation = context.getInitParameter("upload-location");
maxFileSize = Integer.parseInt(context.getInitParameter("max-file-size"));
encodingType = context.getInitParameter("encoding-type");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (ServletFileUpload.isMultipartContent(request)) {
// multipart content로 요청 되었는지 확인한 후 코드를 진행한다.
System.out.println("파일 저장 root 경로 : " + rootLocation);
System.out.println("최대 업로드 파일 용량 : " + maxFileSize);
System.out.println("인코딩 방식 : " + encodingType);
String fileUploadDirectory = rootLocation + "/commons";
File directory = new File(fileUploadDirectory);
/* 파일 저장 경로가 존재하지 않는 경우 디렉토리를 생성한다. */
if (!directory.exists()) {
/* 폴더를 한 개만 생성할꺼면 mkdir, 상위 폴더도 존재하지 않으면
* 한 번에 모든 경로를 생성하기 위해 mkdirs를 이용한다. */
directory.mkdirs();
}
/* 최종적으로 request를 parsing하고 파일을 저장 한 뒤 필요한 내용을 담을 리스트와 맵 */
Map<String, String> parameter = new HashMap<>();
List<Map<String, String>> fileList = new ArrayList<>();
/* 파일 업로드할 시 최대 크기나 임시 저장할 폴더의 경로 등을 포함하기 위한 인스턴스이다. */
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
fileItemFactory.setRepository(new File(fileUploadDirectory));
fileItemFactory.setSizeThreshold(maxFileSize);
/* 서블릿에서 기본 제공하는 클래스가 아닌 commons fileuplaod 라이브러리의 클래스로 임포트 한다. */
ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);
fileUpload.setHeaderEncoding(encodingType);
try {
/* request를 파싱하여 데이터 하나하나를 FileItem 인스턴스로 반환한다. */
List<FileItem> fileItems = fileUpload.parseRequest(request);
for (FileItem item : fileItems) {
/* 폼 데이터는 isFormField 속성이 ture이고, 파일은 false이다. */
System.out.println(item);
}
/* 위에서 출력해본 모든 item들을 다 처리할 것이다. */
for (int i = 0; i < fileItems.size(); i++) {
FileItem item = fileItems.get(i);
if (!item.isFormField()) {
/* 파일 데이터인 경우 */
if (item.getSize() > 0) {
/*
* 파일의 사이즈가 0보다 커야 전송 된 파일이 있다는 의미이므로
* 전송된 파일이 있는 경우에만 처리하고, 0인 경우에는 무시하도록 로직을 작성한다.
*/
String fieldName = item.getFieldName();
String originFileName = item.getName();
int dot = originFileName.lastIndexOf(".");
String ext = originFileName.substring(dot);
String randomFileName = UUID.randomUUID().toString().replace("-", "") + ext;
System.out.println(randomFileName);
/* 저장할 파일 정보를 담은 인스턴스 생성하고 */
File storeFile = new File(fileUploadDirectory + "/" + randomFileName);
/* 저장한다. */
item.write(storeFile);
/* 필요한 정보를 map에 담는다. */
Map<String, String> fileMap = new HashMap<>();
fileMap.put("fieldName", fieldName);
fileMap.put("originFileName", originFileName);
fileMap.put("saveFileName", randomFileName);
fileMap.put("savePath", fileUploadDirectory);
fileList.add(fileMap);
}
} else {
/* 폼 데이터인 경우 */
/*
* 전송된 폼의 name은 getFileName() 으로 받아오고,
* 해당 필드의 value는 getString()으로 받아온다. 하지만 인코딩
* 설정을 하더라도 전송되는 파라미터는 ISO-8859-1로 처리된다.
* 별도로 ISO-8859-1로 해석된 한글을 UTF-8로 변경해주어야 한다.
*/
parameter.put(item.getFieldName(),
new String(item.getString().getBytes("ISO-8859-1"), "UTF-8"));
}
}
System.out.println("parameter : " + parameter);
System.out.println("fileList : " + fileList);
/* Exception 발생 테스트- 업로드 파일 삭제 */
// throw new Exception();
} catch (Exception e) {
/* 어떤 종류의 Exception이 발생하더라도 실패 시 파일을 삭제해야 한다. */
int cnt = 0;
for (int i = 0; i < fileList.size(); i++) {
Map<String, String> file = fileList.get(i);
File deleteFile = new File(fileUploadDirectory + "/"
+ file.get("saveFileName"));
boolean isDelete = deleteFile.delete();
if (isDelete) {
cnt++;
}
}
if (cnt == fileList.size()) {
System.out.println("업로드에 실패한 모든 사진 삭제 완료!");
} else {
e.printStackTrace();
}
}
}
}
}
'백엔드 과정 > Servlet' 카테고리의 다른 글
[Servlet] MIME-TYPE ? (0) | 2022.03.17 |
---|---|
Servlet 문제 풀이 (0) | 2022.03.15 |
[Servlet] cookie와 session (0) | 2022.03.07 |
[Servlet] sendRedirect VS RequestDispatcher (0) | 2022.03.06 |
[Servlet] Response 응답 확인하기 (0) | 2022.03.06 |