고급JAVA 32강 - File 업로드
fileUploadTest.jsp
파일 업로드 테스트
- Servlet 3.0이상에서 파일 업로드를 처리하려면 서블릿에 @MultipartConfig라는 애노테이션을 설정해야 한다.
- MultipartConfig 애노테이션 설정 방법(사용되는 변수 및 역할)
1) location : 업로드한 파일이 임시적으로 저장될 경로를 지정한다.
(기본값 : "")
2) fileSizeThreshold : 이 속성에서 지정한 크기보다 큰 파일은
위의 location에서 지정한 디스크의 임시 디렉토리에 저장한다.
(단위 : byte, 기본값 : 0 (무조건 임시 디렉토리를 사용한다.))
3) maxFileSize : 1개의 파일의 최대 크기 (단위: byte, 기본값: -1L(무제한))
4) maxRequestSize : 서버로 전송되는 Request 데이터의 최대 크기
(단위 : byte, 기본값 : -1L(무제한))
fileSizeThreshold = 1024 1024 10 => 10Mb를 의미
10Mb가 넘어가면 임시폴더가 아닌 저장경로에 저장됨
maxRequestSize : 요구되는 전체 데이터 크기
=> 파일 업로드는 get방식은 사용 불가
각각의 데이터가 저장되는 공간을 part라고 함
part가 여러개인 데이터를 전송한다 = multipart
각각의 part별로 처리할 수 있는 방법이 있어야 함
part가 몇 개가 오는지 모르니까 전체 part에서 하나씩 검사해서 file데이터를 찾아내야 함.
하나의 part가 file 데이터면 file 정보를 가져오기 위한 작업을 해야함.
servlet.http에 있는 Part로 import
content-disposition => part를 구분하는 header
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>File Upload 연습</h2>
<!-- enctype="multipart/form-data" ==> 파일 전송 시 반드시 필요한 속성 -->
<form method="post" enctype="multipart/form-data" action="<%=request.getContextPath()%>/fileUploadTest.do">
이름 :<input type="text" name="username"><br><br>
파일 1개 선택 : <input type="file" name="uploadFile1"><br><br>
다중파일 선택 : <input type="file" name="uploadFile2" multiple><br><br>
<button type="submit">자료 전송</button>
</form>
<br><hr><br>
<a href="<%=request.getContextPath()%>/uploadFileList.do">업로드된 전체 파일 목록 가져오기</a>
</body>
</html>
FileVO
package kr.or.ddit.basic.vo;
public class FileVO {
private String fileName; // 파일 이름
private long fileSize; // 파일 크기
private String uploadStatus;// Upload성공 여부
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public String getUploadStatus() {
return uploadStatus;
}
public void setUploadStatus(String uploadStatus) {
this.uploadStatus = uploadStatus;
}
}
FileUploadTest.java
package kr.or.ddit.fileupload;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import kr.or.ddit.basic.vo.FileVO;
/*
- Servlet 3.0이상에서 파일 업로드를 처리하려면 서블릿에 @MultipartConfig라는 애노테이션을 설정해야 한다.
- MultipartConfig 애노테이션 설정 방법(사용되는 변수 및 역할)
1) location : 업로드한 파일이 임시적으로 저장될 경로를 지정한다. - 윈도우는 temp폴더
(기본값 : "")
2) fileSizeThreshold : 이 속성에서 지정한 크기보다 큰 파일은
위의 location에서 지정한 디스크의 임시 디렉토리에 저장한다.
(단위 : byte, 기본값 : 0 (무조건 임시 디렉토리를 사용한다.))
3) maxFileSize : 1개의 파일의 최대 크기 (단위: byte, 기본값: -1L(무제한))
4) maxRequestSize : 서버로 전송되는 Request 데이터의 최대 크기
(단위 : byte, 기본값 : -1L(무제한))
*/
@WebServlet("/fileUploadTest.do")
@MultipartConfig(
fileSizeThreshold = 1024 * 1024 * 10,
maxFileSize = 1024 * 1024 * 30, maxRequestSize = 1024 * 1024 * 50
)
public class FileUploadTest extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// upload한 파일이 저장될 폴더 설정
String uploadPath = "D:/D_Other/uploadFiles";
// 저장될 폴더가 없으면 새로 생성한다.
File fileUploadDir = new File(uploadPath);
if(!fileUploadDir.exists()) {
fileUploadDir.mkdirs();
}
// 파일이 아닌 일반 데이터는 getParameter()메서드나 getParameterValues()메서드를 이용해서 구한다.
request.setCharacterEncoding("utf-8");
String userName = request.getParameter("username");
System.out.println("일반 파라미터 데이터(username) : " + userName);
//----------------------------------------------------------
String fileName = ""; // 파일명이 저장될 변수 선언
// 업로드한 파일 정보가 저장될 List 객체 생성
List<FileVO> fileList = new ArrayList<FileVO>();
/*
- Servlet 3.0 이상에 새롭게 추가된 Upload용 메서드
1) request.getParts(); ==> 전체 Part객체가 저장된 컬렉션을 반환한다.
2) request.getPart("Part이름") ==> 지정된 이름을 가진 part 객체를 반환한다.(특정한 part를 찾을 때)
*/
for(Part part : request.getParts()) {
// 파일명 구하기
fileName = extractFileName(part);
// 파일명이 공백("")이면 이것은 파일이 아닌 일반 파라미터라는 의미이다.
if(!("".equals(fileName))) {
// 1개의 업로드 파일에 대한 정보를 저장할 객체 생성
FileVO fileVo = new FileVO();
fileVo.setFileName(fileName);
fileVo.setFileSize((int)Math.ceil(part.getSize()/ 1024.0));
// 파일 저장 ==> Part 객체의 write()메서드 이용
try {
part.write(uploadPath + File.separator + fileName);
fileVo.setUploadStatus("Sucess");
} catch (IOException e) {
fileVo.setUploadStatus("Fail : " + e.getMessage());
}
// 처리된 파일 정보를 저장한 객체를 List에 추가
fileList.add(fileVo);
}
}//for문 끝...
request.setAttribute("userName", userName);
request.setAttribute("uploadFileList", fileList);
RequestDispatcher rd = request.getRequestDispatcher("/fileupload/uploadFiles.jsp");
rd.forward(request, response);
} // doPost()메서드 끝...
/*
- Part 구조
1) 파일이 아닐 때 (즉, 일반 파라미터 데이터일 경우)
------------very1867456sdfsd32156421 ==> Part를 구분하는 구분선
content-disposition: form-data; name="username" ==> 파라미터명
==> 빈 줄
tester ==> 파라미터 값
*/
/*
2) 파일일 경우
------------very1867456sdfsd32156421 ==> Part를 구분하는 구분선
content-disposition: form-data; name="uploadFile1"; filename="test1.txt" ==> 파일정보
content-Type: text/plain ==> 파일 종류
==> 빈 줄
asdc123456!@# ==> 파일의 내용
*/
// Part영역에서 읽어올 '파일명'을 찾아 반환하는 메서드
private String extractFileName(Part part) {
String fileName = "";
String contentDisposition = part.getHeader("content-disposition");
// form-data; name="username" ==> 파일이 아닐 때
// form-data; name="uploadFile1"; filename="test1.txt"; ==> 파일일 때
String[] items = contentDisposition.split(";");
for(String item : items) {
if(item.trim().startsWith("filename")) {
// filename="test1.txt" ==> item변수값
fileName = item.substring(item.indexOf("=") + 2, item.length() - 1);
}
}
//file이 아닐 경우 => ""이 반환됨, file일 경우 => file명이 반환됨
return fileName;
}
}
UploadFileList.java
package kr.or.ddit.fileupload;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.or.ddit.basic.vo.FileVO;
/**
* Servlet implementation class UploadFileList
*/
@WebServlet("/uploadFileList.do")
public class UploadFileList extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Upload된 전체 파일 목록을 구성하는 서블릿
String uploadPath = "D:/D_Other/uploadFiles";
// 저장될 폴더가 없으면 새로 생성한다.
File fileUploadDir = new File(uploadPath);
if(!fileUploadDir.exists()) {
fileUploadDir.mkdirs();
}
// 파일이 저장된 폴더에서 전체 파일목록을 구해와서 List에 담아준다.
File[] allFiles = fileUploadDir.listFiles();
List<FileVO> fileList = new ArrayList<FileVO>();
for(File file : allFiles) {
if(file.isFile()) {
FileVO fvo = new FileVO();
fvo.setFileName(file.getName());
fvo.setFileSize((int)Math.ceil(file.length() / 1024.0));
fvo.setUploadStatus("Success");
fileList.add(fvo);
}
}
request.setAttribute("uploadFileList", fileList);
RequestDispatcher rd = request.getRequestDispatcher("/fileupload/uploadFiles.jsp");
rd.forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
uploadFiles.jsp
<%@page import="kr.or.ddit.basic.vo.FileVO"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Servlet File Upload</title>
</head>
<body>
<%
String userName = (String)request.getAttribute("userName");
List<FileVO> fileList = (List<FileVO>)request.getAttribute("uploadFileList");
%>
<%
if(userName!=null){
%>
<h2><%=userName %>님이 방금 업로드 한 파일 목록</h2>
<%
}else{
%>
<h2>전체 업로드 파일 목록</h2>
<%
}
%>
<table border='1'>
<tr>
<td>파일이름</td><td>파일크기</td><td>업로드 상태</td><td>비고</td>
</tr>
<%
if(fileList!=null){
for(FileVO fileVo : fileList){
%>
<tr>
<td><%=fileVo.getFileName() %></td>
<td><%=fileVo.getFileSize() %></td>
<td><%=fileVo.getUploadStatus() %></td>
<td><a href="<%=request.getContextPath()%>/fileDownload.do?filename=<%=fileVo.getFileName()%>">Download</a></td>
</tr>
<%
}
}
%>
</table>
<br><hr><br>
<a href="<%=request.getContextPath()%>/fileupload/fileUploadTest.jsp">파일 업로드 시작문서로 가기</a>
</body>
</html>
FileDownload.java
package kr.or.ddit.fileupload;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/fileDownload.do")
public class FileDownload extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
// 파라미터로 넘어오는 filename 구하기
String fileName = request.getParameter("filename");
String downLoadPath = "d:/d_other/uploadFiles";
String filePath = downLoadPath + File.separator + fileName;
File file = new File(filePath);
OutputStream out = null;
FileInputStream fin = null;
if(file.exists()) { // 파일이 있을 때...
// ContentType 설정
response.setContentType("application/octet-stream; charset=utf-8"); //파일 다운로드 할 때 octet-stream가 들어가야 함
//response객체의 content-disposition헤더 속성 설정하기
String headerKey = "Content-Disposition";
// 한글 getFileNameEncoding 메서드 사용
String downFileName = getFilenameEncoding(fileName, getBrowser(request));
String headerValue = "attachment; filename=\"" + downFileName + "\";";
response.setHeader(headerKey, headerValue);
getBrowser(request); // 한글이 어떻게 나오는지 검사
try {
// 출력용 스트림 객체 생성 ==> response객체 이용
out = response.getOutputStream();
// 파일 입력용 스트림 객체 생성
fin = new FileInputStream(file);
byte[] buffer = new byte[1024 * 100]; // 한번에 100KB씩 읽어오라는 뜻
int len = 0;
// byte배열을 이용하여 파일 내용을 읽어와 출력용 스트림을 이용하여 클라이언트에게 전송한다.
while((len = fin.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
} catch (IOException e) {
System.out.println("입출력 오류 : " + e.getMessage());
}finally {
if(fin!=null)try {fin.close();} catch(Exception e) {}
if(out!=null)try {out.close();} catch(Exception e) {}
}
}else { // 파일이 없을 때
response.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
response.getWriter().println("<h3>" + fileName + "파일은 존재하지 않습니다.</h3>");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
// 사용자의 브라우저 알아내기
private String getBrowser(HttpServletRequest request) {
String header = request.getHeader("User-Agent");
//System.out.println(header);
if(header.indexOf("MSIE") > -1) {
return "MSIE";
}else if(header.indexOf("Chrome") > -1){
return "Chrome";
}else if(header.indexOf("Opera") > -1) {
return "Opera";
}else if(header.indexOf("Trident/7.0") > -1) { // IE 11이상
return "MSIE";
}
return "Firefox";
}
// 브라우저별로 한글 파일명을 인코딩하는 메서드
private String getFilenameEncoding(String filename, String browser) {
String encodedFilename = null;
try {
if(browser.equals("MSIE")) {
encodedFilename = URLEncoder.encode(filename, "utf-8").replaceAll("\\+", "%20");
}else if(browser.equals("Firefox")) {
encodedFilename = "\"" + new String(filename.getBytes("utf-8"), "8859_1") + "\"";
}else if(browser.equals("Opera")) {
encodedFilename = "\"" + new String(filename.getBytes("utf-8"), "8859_1") + "\"";
}else if(browser.equals("Chrome")) {
StringBuffer sb = new StringBuffer();
for(int i = 0; i <filename.length(); i++) {
char c = filename.charAt(i);
if(c> '-') {
sb.append(URLEncoder.encode(""+c, "utf-8"));
}else {
sb.append(c);
}
}
encodedFilename = sb.toString();
}else {
throw new RuntimeException("지원하지 않는 브라우저입니다.");
}
} catch (Exception e) {
// TODO: handle exception
}
return encodedFilename;
}
}
Author And Source
이 문제에 관하여(고급JAVA 32강 - File 업로드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gksmf6699/고급JAVA-32강-File-업로드저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)