이전글: https://coding-chronicle.tistory.com/101
파일 업로드 및 저장 - 01, html
개요 수작업으로 게시글처럼 보이도록 개행문자를 기준으로 나눠 태그를 작성하던 중 우연히 위그지그 를 발견하게 되어 관련 에디터 CKEditor의 이미지 업로드를 구현하기 위해 공부한 파일 업
coding-chronicle.tistory.com
이전글에서 알아본 html을 토대로 파일을 전송해서 실제 내 컴퓨터에 저장하는 방법을 알아보겠다.
HTML
<form action="FileUploadTest" method="post" enctype="multipart/form-data">
작성자<input type="text" name="fileWriter"><br>
파일<input type="file" name="fileName"><br>
파일설명<br/><textarea name="fileDescription" rows="5" cols="30"></textarea><br/><br/>
<input type="submit" value="업로드">
</form>
- 위의 HTML을 토대로 서버에 파일 데이터를 전송한다.
Servlet
이전 포스팅에서 확인 했듯이 enctype="multipart/form-data"으로 form 데이터를 전송한 경우 file의 데이터는 request.getParameter()로 확인할 수 없다.
이렇듯 getParameter()로 확인할 수 없는 file 데이터는 Part 인터페이스를 사용하여 값을 수신한다.
Part 인터페이스를 사용하기 전 데이터의 해석 방식을 변경하기 위해 선행 처리 작업이 필요하다.
파일의 데이터 수신 시 form의 전송방식이 달라지기 때문에 enctype을 지정하지 않았을 경우의 form 속성인 enctype="application/www-form-urlencoded" 데이터 해석 방식으로 실제 전송된 데이터 형식인 multipart/form-data 데이터를 해석하게 되면 잘못된 값으로 해석할 수 있는 여지가 있기에 Servlet에게 해석 방법을 알려줄 필요가 있다.
만약 해석방법을 알려주지 않고 multipart/form-data를 수신한 경우엔 아래와 같은 오류를 만나게 될 것이다.
multipart/form-data로 해석하라고 알려주는법:
MultipartConfig()
- 클래스에 @MultipartConfig()를 작성해 주면 알아서 multipart/form-data로 방식으로 해석한다.
@WebServlet("/FileUploadTest")
@MultipartConfig( // 이부분을 작성해야 file 해석 가능
maxFileSize = 1024 * 1024 * 3,
maxRequestSize = 1024 * 1024 * 3)
public class Test extends HttpServlet{
// ... 수신, 응답 처리
}
- 속성값은 아래와 같다.
- 자세한 내용은 공식 문서를 확인하길 바란다.
docs: https://docs.oracle.com/javaee/7/api/javax/servlet/annotation/MultipartConfig.html
MultipartConfig (Java(TM) EE 7 Specification APIs)
The maximum size allowed for uploaded files. The default is -1L, which means unlimited.
docs.oracle.com
@MultipartConfig(
fileSizeThreshold= 파일이 디스크에 임시 저장되기 전까지의 파일 크기,
기본크기는 0바이트
location= fileSizeThreshold 설정을 초고하는 경우 파일을 임시로 저장할 디렉터리 위치,
기본값=""
maxFileSize = 업로드 파일 허용 최대 크기,
파일의 크기가 이 값보다 크면 예외(IllegalStateException)이 발생
maxRequestSize = 요청 허용 최대 크기
모든 파일의 전체 크기가 이 값 보다 크면 예외 발생, 기본크기는 무제한
)
- 어노테이션을 사용하지 않고, web.xml에 아래와 같이 명시할 수도 있다.
<multipart-config>
<max-file-size>123456</max-file-size>
<max-request-size>123456</max-request-size>
<file-size-threshold>0</file-size-threshold>
</multipart-config>
file 데이터를 해석해 보자
Part 인터페이스
- multipart/form-data로 들어온 file 데이터를 해석할 때 사용한다.
This class represents a part or form item that was received within a multipart/form-data POST request.
이 클래스는 multipart/form-data POST 요청 내에서 수신된 부분 또는 양식 항목을 나타냅니다.
docs: https://docs.oracle.com/javaee/7/api/javax/servlet/http/Part.html
Part (Java(TM) EE 7 Specification APIs)
A convenience method to write this uploaded item to disk. This method is not guaranteed to succeed if called more than once for the same part. This allows a particular implementation to use, for example, file renaming, where possible, rather than copying a
docs.oracle.com
- Part에 대한 여러 메서드가 있는데 정확히 무슨 역할을 하는지 잘 모르겠으니 출력해보자.
Collection<Part> parts = request.getParts();
for(Part part: parts) {
System.out.println("headerNames: " + part.getHeaderNames());
System.out.println("contentType: " + part.getContentType());
System.out.println("name: " + part.getName());
System.out.println("size: " + part.getSize());
System.out.println("sybmittedFileName: " + part.getSubmittedFileName());
System.out.println("content-disposition: " + part.getHeader("content-disposition"));
System.out.println();
}
- 제일 앞과 제일 뒤의 데이터는 input text 데이터이므로 무시하고 중간의 file 데이터만 확인하자.
- 파일의 크기를 알 수 있는 getSize와 파일의 이름인 getSybmittedFileName 정도만 알고 있으면 될 것 같다.
서버에 저장
final Part part = request.getPart("fileName"); // form의 name값인 fileName 데이터 얻기
final String getFileName = part.getSubmittedFileName();
final String uuidFileName = UUID.randomUUID().toString(); // 파일명이 중복되지 않도록 uuid 랜덤값을 파일명으로 지정
final String extentionName = getFileName.substring(getFileName.lastIndexOf(".")); // 확장자 얻기
final Path path = Paths.get("C:\\uploadTest"); // 저장 경로
if(!Files.exists(path)) { // 저장 경로 폴더가 없다면
Files.createDirectory(path); // 폴더 생성
}
part.write(path + "\\" + uuidFileName + extentionName); // 해당 경로에 파일 저장
'JAVA > Java' 카테고리의 다른 글
[servlet/jsp/jstl] 개행문자를 기준으로 나눠 반복 처리를 하는 방법 (0) | 2023.09.13 |
---|---|
[Servlet & JSP] 게시판 요구사항 작성 (0) | 2023.08.27 |
[JAVA] 자바의 자료구조 큐 (0) | 2023.06.26 |
[JAVA] 버퍼 (0) | 2023.06.22 |