▣ 파일 업로드
게시글의 첨부파일, 프로필, 쇼핑몰 상품 이미지 등록 등 웹 환경에서 파일 업로드는 많은 곳에서 사용
Servlet 3.0 이전에는 전송된 File을 쉽게 처리할 수 있도록 지원해주는 API가 없음.
따라서 Servlet/Jsp 환경에서 파일업로드를 구현할 때는 파일 업로드와 관련된 라이브러리를 사용
* 라이브러리를 사전 설치 필요
① http://jakarta.apache.org/ 접속 후 FileUpload 와 commons-io 라이브러리 설치
② 각 jar를 lib에 추가
⭐ 반드시 form 태그에 enctype="multipart/form-data" 설정
- 이 방식은 <form> 요소가 파일이나 이미지를 서버로 전송할 때 주로 사용
<form action="${contextPath}/upload.do" method="post" enctype="multipart/form-data">
</form>
HTML에서는 기본적으로 파일을 첨부할 수 있는 API를 제공
<INPUT> 태그의 type 속성값을 fille 로 지정
또한 <FORM>태그의 method 속성이 post여야 함.
파일 업로드를 처리할 서블릿 작성
import ... //생략
@WebServlet("/upload.do")
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static String FILE_REPO = "C:\\file_repos";
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
String encoding = "utf-8";
//업로드할 파일 경로 지정
File currentDirPath = new File(FILE_REPO);
DiskFileItemFactory facotry = new DiskFileItemFactory();
factory.setRepository(currentDirPath); // 파일 경로 설정
factory.setSizeThreshold(1024*1024); // 최대 업로드 가능한 파일 크기 설정
ServletFileUpload fileUpload = new ServletFileUpload(Factory);
List fileList = new ArrayList();
try {
List items = fileUpload.parseRequest(request); // request 객체에서 매개변수를 List로 가져옴
for(int i = 0; i < items.size(); i++) {
FileItem fileItem = (FileItem) items.get(i)
if (fileItem.isFormField()) {
System.out.println(fileItem.getFieldName() + "=" + fileItem.getString(encoding));
} else {
System.out.println("매개변수이름: " + fileItem.getFieldName());
System.out.println("파일이름: " + fileItem.getName());
System.out.println("파일크기: " + fileItem.getSize() + "bytes");
// 업로드한 파일 이름을 가져옴
if(fileItem.getSize() > 0) {
int idx = fileItem.getName().lastIndexOf("\\");
if (idx == -1) {
idx = fileItem.getName().lastIndexOf("/");
}
String fileName = fileItem.getName().substring(idx+1);
fileList.add(fileName);
File uploadFile = new File(currentDirPath + "\\" + fileName);
fileItem.write(uploadFile);
} //end if
} // end if
} // end for
} catch (Exception e) {
e.printStackTrace();
}
request.setAttribute("fileList",fileList);
RequestDispatcher dispatch = request.getRequestDispatcher("upload.jsp");
dispatch.forward(request,response);
}
}
파일 업로드 관련 API
① DiskFileItemFactory 클래스가 제공하는 메서드
-DiskFileItemFactory는 업로드된 파일을 저장할 저장소와 관련된 클래스
setRepository( )
- 파일을 저장할 디렉터리를 설정, 업로드 된 파일을 저장할 위치를 File 객체로 지정
setSizeThreshold()
- 최대 업로드 가능한 파일 크기를 설정( byte 단위로 지정 )
≫ 예를 들어 이 값을 1024로 지정한 경우 1024byte 이상의 파일을 업로드 했을 때 메모리에 있던 파일의 바이너리 데이터를 저장소에 임시파일로 잠시 저장함.
이렇게 임시파일로 저장하는 이유는 대용량 파일을 업로드 했을 때 그만한 크기의 데이터를 웹어플리케이션이 동작하는 JVM 메모리상에 모두 로드하는 것은 부담이 되기 때문
임시파일로 저장되었던 파일은 이후에 FileItem. write( )와 delete( ) 메서드를 통해 실제 파일로 변경되거나 제거
② ServletFileUpload 클래스가 제공하는 메서드
- ServletFileUpload 클래스는 HTTP 요청에 대한 HttpServletRequest 객체로부터 multipart/form-data 형식으로 넘어온 HTTP Body 부분을 다루기 쉽게 변환(parse)해주는 역할을 수행
parseRequest( )
- 전송괸 매개변수를 List 객체로 얻음.
- parseRequest() 메서드 수행시 FileItem이라는 형식으로 변환
getItemIterator( )
- 전송된 매개변수를 Iterator 타입으로 얻음.
FileItem
사용자가 업로드한 File 데이터나 사용자가 input text에 입력한 일반 요청 데이터에 대한 객체
⭐ isFormField() 메서드의 리턴값이 true이면 text 같은 일반 입력 데이터, false 이면 파일 데이터
파일 저장코드
File.separator는 운영체제별로 다른 파일경로로 구분자를 갖고있음
- window 환경 디렉터리 구분 : \ (\) , \\
- linux 계열 : /
따라서 업로드한 파일 경로의 마지막 separator 뒤에 오는 값이 실제 파일명
(ex: C:\\app\\test.txt 에서 test.txt가 실제 파일명)
크롬의 경우 POST로 파일 전송시 실제 파일명만 넘겨주는 반면 인터넷 익스플로러의 경우 사용자의 드라이버 경로,절대경로 전부를 리턴해주기 때문에 파일명을 추출할 때 이를 주의
▣ 파일 다운로드
파일 다운로드를 처리할 서블릿 작성
import .. //생략
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;chareset=utf-8");
String file_repo = "C:\\file_repo";
String fileName = (String)request.getParameter("fileName");
System.out.println("fileName= " + fileName);
// response에서 OutputStream 객체를 가져옴
OutputStream out = response.getOutputStream();
String downFile = file_repo + "\\" + fileName;
File f = new File(downFile);
response.setHeader("Cache-Control","no-cache");
response.addHeader("Cache-disposition", "attachment; fileName="+fileName);
FileInputStream in = new FileInputStream(f);
//버퍼 기능을 이용해 파일에서 버퍼로 데이터를 읽어와 한꺼번에 출력
byte[] buffer = new byte[1024*8]; //8kbyte씩 일음
while(true) {
int count = in.read(buffer);
if(count==-1)
break;
out.write(buffer,0,count);
}
in.close();
out.close();
}
케시 제어를 위한 응답 헤더
response.setHeader("Cache-Control", "no-cache");
- 데이터가 변경되었음에도 불구하고 웹 브라우저는 캐시에 저장된 데이터를 출력하기 때문에 변경된 내용으로 적용 안됨.
- 게시판과 같이 내용이 자주 변경되는 사이트는 웹 브라우저 캐시가 적용되면 사용자는 변경된 내용을 확인할 수 없음
- Cache-control 응답헤더 : HTTP 1.1 버전에서 지원하는 헤더. 값을 'no-cache'로 지정하면 캐시에 저장하지 않음
Content-Disposition
- ContentDisposition은 HTTP Response Body에 오는 컨텐츠의 기질/성향을 알려주는 속성
Content-Disposition : attachment; filename="hello.jps"
이때 Body에 오는 filename을 다운로드 받으라는 뜻
FileInputStream 클래스
FileInputStream(File file) : 주어진 File 객체가 가리키는 파일을 바이트 스트림으로 읽기 위한 객체 생성
FileInputStream(String name) : 주어진 이름이 가리키는 파일을 바이트 스트림으로 읽기 위한 객체 생성
outputStream 클래스
'개발 > Programming' 카테고리의 다른 글
한글 인코딩 UTF-8 설정 (0) | 2021.09.17 |
---|---|
Flow chart (순서도) (0) | 2021.09.15 |
제이쿼리(Jquery) (0) | 2021.07.21 |
[JSP] 표현언어와 JSTL (0) | 2021.07.14 |
[JSP] 액션 태그 (0) | 2021.07.04 |