자바 파일 업로드 전면 분석
파일 업로드 란 사용자 의 정 보 를 저장 하 는 것 이다.
파일 업로드 가 왜 필요 합 니까?
사용자 가 등록 할 때 사진 을 제출 해 야 할 수도 있 습 니 다.그럼 이 사진 은 저장 해 야 지.
업로드 구성 요소(도구)는 왜 우리 가 업로드 도 구 를 사용 해 야 합 니까?
왜 우 리 는 구성 요 소 를 올 려 야 합 니까?클 라 이언 트 의 데 이 터 를 가 져 오 려 면 getParameter()방법 으로 가 져 옵 니 다.
파일 데 이 터 를 업로드 하 는 것 은 MIME 프로 토 콜 을 통 해 분할 되 었 고 폼 은 바 이 너 리 패키지 가 되 었 습 니 다.즉,getParameter()는 업로드 파일 의 데 이 터 를 가 져 올 수 없습니다.
우선 파일 업로드 http 가 어떻게 데 이 터 를 가 져 갔 는 지 살 펴 보 겠 습 니 다.
jsp 페이지,폼 은 enctype:multipart/form-data 를 지정 해 야 합 니 다.
<form action="${pageContext.request.contextPath }/servlet/UploadServlet1" enctype="multipart/form-data" method="post">
:<input type="text" name="username"><br/>
1:<input type="file" name="file1"><br/>
2:<input type="file" name="file2"><br/>
<input type="submit" value=" ">
</form>
http 패키지Servlet 에서 getParameter()를 사용 하여 데 이 터 를 가 져 오 려 고 시도 합 니 다.
String ss = request.getParameter("username");
System.out.println(ss);
getParameter 를 직접 사용 하면 데 이 터 를 얻 을 수 없습니다.그럼 우리 어 떡 하지???request 대상 은 ServletInputStream 흐름 을 제공 하여 데 이 터 를 읽 어 줍 니 다.
우 리 는 파일 을 읽 어 보 았 다.
ServletInputStream inputStream = request.getInputStream();
byte[] bytes = new byte[1024];
int len = 0;
while ((len = inputStream.read(bytes)) > 0) {
System.out.println(new String(bytes, 0, len));
}
jsp 페이지 에 input 컨트롤 을 하나 더 추가 합 니 다.
<input type="text" name="password">
내 가 업로드 한 텍스트 파일 의 내용 은 111111 입 니 다.읽 기 효 과 는 다음 과 같 습 니 다.이제 우 리 는 파일 을 업로드 한 데 이 터 를 읽 을 수 있 습 니 다.그러나 지금 문 제 는 또 왔 습 니 다.어떻게 파일 을 업로드 하여 서버 에 전송 하 는 데이터 와 분리 합 니까?위 에서 그림 에서 우 리 는 이미 보 았 다.그들 은 한데 섞 인 것 이다.
우리 의 일반적인 방법 으로 는 분리 하기 어렵 기 때문에 구성 요 소 를 업로드 해 야 합 니 다.
업로드 구성 요 소 는 두 가지 FileUpload[조작 이 복잡 합 니 다]SamrtUpload[조작 이 간단 합 니 다]FileUpload
FileUpload 구성 요 소 를 사용 하려 면 jar 패키지 두 개 를 가 져 와 야 합 니 다.
commons-io Commons-fileupload 개발 절차 생 성 해상도 기 공장 대상[DiskFileItemFactory]해상도 기 공장 생 성 해상도 기[ServletFileUpload]호출 해상도 기 방법 으로 request 대상 을 분석 하고 모든 업로드 내용[list]을 얻어 list 를 옮 겨 다 니 며 각 대상 이 업로드 파일 인지 여 부 를 판단 합 니 다.일반 폼 필드 라면,필드 이름과 필드 값 을 가 져 옵 니 다.파일 을 업로드 하 는 경우 InputSteam 방법 으로 입력 흐름 을 가 져 와 업 로드 된 데 이 터 를 읽 고 빠르게 입문 합 니 다.
try{
//1.
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.
ServletFileUpload upload = new ServletFileUpload(factory);
//3.
if(!upload.isMultipartContent(request)){
// ,
return;
}
// ,
List<FileItem> list = upload.parseRequest(request); //FileItem
// list, fileItem
for(FileItem item : list){
if(item.isFormField()){
//
String name = item.getFieldName(); //
String value = item.getString();
System.out.println(name + "=" + value);
}else{
//
String filename = item.getName(); // C:\Documents and Settings\ThinkPad\ \1.txt
filename = filename.substring(filename.lastIndexOf("\\")+1);
InputStream in = item.getInputStream(); //
int len = 0;
byte buffer[]= new byte[1024];
String savepath = this.getServletContext().getRealPath("/upload");
FileOutputStream out = new FileOutputStream(savepath + "\\" + filename); // upload
while((len=in.read(buffer))>0){
out.write(buffer, 0, len);
}
in.close();
out.close();
}
}
}catch (Exception e) {
e.printStackTrace();
}
테스트 일반 필드 와 업로드 한 파일 을 모두 읽 을 수 있 습 니 다!SmartUpload
SmartUpload 구성 요 소 를 사용 하려 면 smartupload.jar 개발 패 키 지 를 가 져 와 야 합 니 다.
쾌속 입문
//
SmartUpload smartUpload = new SmartUpload();
//
smartUpload.initialize(this.getServletConfig(), request, response);
try {
//
smartUpload.upload();
// , request 。 smartUpload
String password = smartUpload.getRequest().getParameter("password");
System.out.println(password);
// uploadFile
smartUpload.save("uploadFile");
} catch (SmartUploadException e) {
e.printStackTrace();
}
테스트마찬가지 로,우 리 는 파일 을 uploadFile 폴 더 에 업로드 할 수 있다.코드 양도 확실히 많이 줄 었 어!
일반 필드 의 인자 도 가 져 올 수 있 습 니 다.
파일 이름 의 중국어 난 코드 와 데 이 터 를 업로드 하 는 중국어 난 코드 를 중국어 로 바 꾸 면 난 코드 가 됩 니 다.
양식 에 제출 된 중국어 데이터 도 엉망 이 되 었 다.
위 에서 이미 말 했 듯 이 파일 의 데 이 터 를 업로드 하 는 폼 은 바 이 너 리 패 키 징 을 했 기 때문에 request 를 사용 하여 데이터 인 코딩 을 하면 폼 이 제출 한 데이터 에 효과 가 없습니다!
FileUpload 난 코드 해결
FileUpload 를 사용 하여 어 지 러 운 문 제 를 해결 하 는 것 은 매우 간단 하 다.
중국어 파일 이름 난 장 판 을 해결 하고 해석 기 를 받 은 후 해석 기의 인 코딩 을 UTF-8 로 직접 설정 하면 됩 니 다!
// upload
fileUpload.setHeaderEncoding("UTF-8");
폼 데이터 의 난 장 판 을 해결 하고 폼 값 을 가 져 올 때 UTF-8 인 코딩 에 따라 가 져 옵 니 다.
String value = fileItem.getString("UTF-8");
효과:SmartUpload 난 코드 해결
이 구성 요 소 는 어 지 러 운 문 제 를 해결 하 는 데 좀 번 거 로 워 서 인터넷 에서 여러 가지 방법 을 찾 았 지만 간단 한 것 을 찾 지 못 했다.
따라서 데이터 가 중국어 와 관련 되 지 않 으 면 SmartUpload 구성 요 소 를 사용 하고 중국어 데이터 와 관련 되면 FileUpload 구성 요 소 를 사용 하 세 요!
여러 파일 업로드,동적 업로드 컨트롤 추가
내 가 지금 업로드 할 파일 이 여러 개 있 고 업로드 할 갯 수 는 확실 하지 않다 고 가정 하 자.그럼 우리 어 떡 하지??
우 리 는 파일 을 업로드 하 는 컨트롤 을 페이지 에 많이 표시 할 수 없습니다.이렇게 하면 아름 답지 않 습 니 다.사용자 가 그렇게 많은 컨트롤 을 사용 하지 못 한다 면 낭비 할 것 입 니 다.
따라서 파일 을 업로드 하 는 컨트롤 을 동적 으로 추가 하려 면 사용자 가 파일 을 업로드 하려 면 동적 으로 컨트롤 을 생 성하 면 됩 니 다!
분석 하 다.
페이지 에 컨트롤 을 동적 으로 생 성 하려 면 자바 스 크 립 트 코드 를 사용 하 는 것 이 아 닙 니 다.
그럼 우 리 는 어떻게 해 야 되 지?
이렇게 하 세 요:사용자 가 파일 을 업로드 하려 고 할 때 단 추 를 누 르 고 이벤트 바 인 딩 을 누 르 면 파일 업로드 컨트롤 을 생 성 합 니 다.
더욱 완벽 하 게 하기 위해 파일 업로드 컨트롤 이 생 성 될 때마다 삭제 단 추 를 제공 하여 이 컨트롤 을 삭제 합 니 다!
우 리 는 div 를 사용 하여 우리 가 생 성 할 컨트롤 과 삭제 단 추 를 불 러 와 야 합 니 다.사용자 가 삭 제 를 클릭 할 때 삭제 단추 와 파일 업로드 컨트롤 을 함께 숨겨 야 합 니 다.그래서 내장 div 를 사용 하 는 것 이 좋 습 니 다!
코드 페이지 코드:
<table>
<tr>
<td> :</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td> </td>
<td><input type="button" value=" "> </td>
</tr>
<tr>
<td>
<div>
</div>
</td>
</tr>
</table>
javaScript 코드
<script type="text/javascript">
function addUploadFile() {
//
var input = document.createElement("input");
input.type = 'file';
input.name = 'fileName';
//
var del = document.createElement("input");
del.type = 'button';
del.value = ' ';
// div
var innerDiv = document.createElement("div");
// div
innerDiv.appendChild(input);
innerDiv.appendChild(del);
// div , div div
var outterDiv = document.getElementById("file");
outterDiv.appendChild(innerDiv);
//
del.onclick = function dele() {
// div remove div
this.parentNode.parentNode.removeChild(this.parentNode);
}
}
</script>
파일 업로드 세부 사항 은 업로드 파일 의 크기 가 우리 가 설정 한 파일 의 크기 보다 크 면 업로드 할 때 임시 파일 로 업로드 데 이 터 를 저장 합 니 다.업로드 가 끝 난 후에 우 리 는 임시 파일 업로드 파일 의 위 치 를 삭제 해 야 합 니 다.WEB 서버 관리 하에 서 는 안 됩 니 다.그렇지 않 으 면 안전 문제 가 발생 할 수 있 습 니 다.[다른 사람들 은 수단 을 통 해 업로드 파일 을 수정 할 수 있 습 니 다]업로드 파일 이름 이 같 으 면 원래 의 업로드 파일 을 덮어 씁 니 다.우 리 는 하나 밖 에 없 는 파일 이름 을 만들어 야 한다.사용자 수가 많 으 면 파일 을 많이 업로드 합 니 다.그러면 우 리 는 한 디 렉 터 리 에 모든 업로드 파일 을 저장 해 서 는 안 된다.그러면 디스크 가 무 너 질 수 있다.그래서 우 리 는 올 린 파일 을 다른 디 렉 터 리 로 흩 어 뜨 려 야 한다.분석 하 다.임시 파일 문 제 를 삭제 하 는 것 은 매우 간단 합 니 다.모든 작업 이 끝 난 후에 FileItem 의 delete()방법 을 사용 하면 됩 니 다.
업로드 파일 의 위 치 를 WEB 서버 관리 하에 있 지 못 하 게 합 니 다.업로드 파일 의 위 치 를 WEB-INF/디 렉 터 리 에 두 면 됩 니 다!
파일 이름 이 같은 문 제 는 UUID+사용자 가 업로드 한 파일 이름 으로 업로드 파일 이름 을 저장 할 수 있 습 니 다.이런 파일 이름 은 유일무이한 것 이다.
올 린 파일 을 분산 시 키 려 면 HashCode 알고리즘 을 사용 하여 분산 시 켜 야 합 니 다.
낮은 4 비트 1 급 디 렉 터 리 생 성 5-8 비트 2 급 디 렉 터 리 코드 생 성
다음은 저희 가 비교적 완벽 한 업로드 파일 코드 를 쓰 겠 습 니 다.
hashCode 알고리즘 으로 저 장 된 디 렉 터 리 를 분산 시 킵 니 다.
private String makeDirPath(String fileName, String path) {
//
int hashCode = fileName.hashCode();
int dir1 = hashCode & 0xf;
int dir2 = (hashCode & 0xf0) >> 4;
String dir = path + "\\" + dir1 + "\\" + dir2;
// ,
File file = new File(dir);
if (!file.exists()) {
file.mkdirs();
}
//
return dir;
}
유일한 파일 이름 만 들 기
private String makeFileName(String fileName) {
// UUID , 。
return UUID.randomUUID().toString() + "_"+ fileName;
}
업로드 코드
//
DiskFileItemFactory factory = new DiskFileItemFactory();
//
ServletFileUpload fileUpload = new ServletFileUpload(factory);
// upload
fileUpload.setHeaderEncoding("UTF-8");
//
if(!fileUpload.isMultipartContent(request)){
// ,
return;
}
try {
// request , List【 】
List<FileItem> list = fileUpload.parseRequest(request);
// List,
for (FileItem fileItem : list) {
//
if (fileItem.isFormField()) {
//
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");
System.out.println(name + " = " + value);
} else {
//
// 【 】
String fileName = fileItem.getName();
//
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
//
fileName = makeFileName(fileName);
InputStream inputStream = fileItem.getInputStream();
// ,
String path = this.getServletContext().getRealPath("/WEB-INF/uploadFile");
//
String realPath = makeDirPath(fileName, path);
FileOutputStream outputStream = new FileOutputStream(realPath + "\\" + fileName);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = inputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, len);
}
inputStream.close();
outputStream.close();
//
fileItem.delete();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
효과:디 렉 터 리 를 분산 시 키 는 데 성 공 했 고 파일 이름 도 유일무이 합 니 다.업로드 디 렉 터 리 에 있 는 파일 을 보 여 줍 니 다.다운 로드 를 제공 합 니 다.
respose 대상 을 설명 할 때 이미 파일 다운 로드 를 설명 했다.이번에 우 리 는 직접 작은 사례 를 써 서 파일 다운 로드 를 공 고 히 할 것 이다.
디 렉 터 리 에 있 는 파일 업로드 3 개
분석 하 다.
우선 디 렉 터 리 에 있 는 파일 을 모두 열거 해 야 한다.뒤에 파일 이름 에 따라 파일 을 다운로드 해 야 하기 때문에 우 리 는 맵 집합 으로 모든 파일 을 저장 합 니 다.
파일 다운로드 부분도 간단 하 다.파일 이름과 업로드 파일 위치 에 따라 해당 하 는 파일 을 찾 아 읽 기와 쓰 기 를 한 다음 메시지 헤드 를 수정 해 다운로드 하면 된다.
업로드 파일 을 불 러 오 는 경 로 를 얻 고 재 귀 를 통 해 모든 파일 을 찾 습 니 다.사용자 가 코드 를 다운로드 할 수 있 도록 WEB-INF/디 렉 터 리 에 저 장 된 파일 을 모두 Map 집합 에 저장 합 니 다.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//
String filePath = this.getServletContext().getRealPath("/WEB-INF/uploadFile");
Map map = new HashMap();
// , Map
getAllFiles(new File(filePath), map);
request.setAttribute("map", map);
request.getRequestDispatcher("/listFile.jsp").forward(request, response);
}
private void getAllFiles(File filePath, Map map) {
// ,
if (!filePath.isFile()) {
// ( , )
File[] files = filePath.listFiles();
for (File file : files) {
// ( )
getAllFiles(file, map);
}
} else {
// else ,
//
String fileName = filePath.getName().substring(filePath.getName().lastIndexOf("_") + 1);
// key, value map
map.put(filePath.getName(), fileName);
}
}
JSP 페이지 에 다운로드 가능 한 파일 보이 기
<c:forEach items="${map}" var="me">
<c:url var="url" value="/DownFileServlet">
<c:param name="fileName" value="${me.key}"></c:param>
</c:url>
${me.value}<a href="${url}" rel="external nofollow" > !</a><br>
</c:forEach>
다운로드 가능 한 Servlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//
String fileName = request.getParameter("fileName");
// , 。
fileName = new String(fileName.getBytes("ISO8859-1"), "utf-8");
//
String path = this.getServletContext().getRealPath("/WEB-INF/uploadFile");
// hashCode ,
String fileRealPath = makeFilePath(fileName, path);
System.out.println(fileRealPath);
//
File file = new File(fileRealPath);
if (!file.exists()) {
request.setAttribute("message", " !");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return ;
}
//
//
FileInputStream inputStream = new FileInputStream(fileRealPath);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = inputStream.read(bytes)) > 0) {
response.getOutputStream().write(bytes, 0, len);
}
inputStream.close();
// , ,
String name = fileName.substring(fileName.lastIndexOf("_") + 1);
response.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(name, "UTF-8"));
}
private String makeFilePath(String fileName, String path) {
int hashCode = fileName.hashCode();
int dir1 = hashCode & 0xf;
int dir2 = (hashCode & 0xf0) >> 4;
String dir = path + "\\" + dir1 + "\\" + dir2 +"\\"+ fileName;
return dir;
}
효과.글 에 잘못된 부분 이 있 으 면 지적 을 환영 하고 서로 교류 합 니 다.우리 에 대한 여러분 의 지지 에 감사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.