[NewFile.html]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
</head>
<body>
<div>
<h1>파일 첨부 양식</h1>
<form action="/servlet/upload" method="post" enctype="multipart/form-data">
<div>
<label for="uploader">업로더</label>
<input type="text" id="uploader" name="uploader">
</div>
<div>
<label for="attach">파일첨부</label>
<input type="file" id="attach" name="attach">
</div>
<div>
<button type="submit">첨부하기</button>
</div>
</form>
<div id="preview"></div>
</div>
<script>
//<input type="file" id ="attach">인 요소에 어떤 파일을 첨부하는 경우 change 이벤트가 발생한다.
$('#attach').change(function() {
//첨부된 파일의 크기가 50MB(1024*1024*50) 초과이면 첨부를 못하게 막는다.
var size=this.files[0].size //첨부된 파일의 크기
var limit=1024*1024*50; // 크기제한
if(size>limit){
alert('첨부 파일의 최대 크기는 50MB입니다.');
this.value=''; //첨부된 파일을 취소한다.
return;
}
//첨부된 파일의 형식이 이미지가 아니면 첨부를 막는다.
var type = this.files[0].type; //첨부된 파일의 형식
if(!type.startsWith('image/')){alert('이미지만 첨부할 수 있습니다.');
this.value='';//첨부된 파일을 취소한다.
return;
}
// <div id="preview">첨부된 파일 미리보기
var reader =new FileReader();
reader.onload=function(event){
var img=new Image();
$(img).attr('src',event.target.result);
$(img).attr('width','192px');
$('#preview').html(img);
}
reader.readAsDataURL(this.files[0]);
})
</script>
</body>
</html>
파일 첨부 선행 작업
1.http://servlets.com/ 접속
2.COS File Upload Library - cos-22.05.zip 다운로드
3.zip 압축 해제 후 lib/cos.jar 라이브러리 -> 프로젝트 webapp/WEB-INF/lib/cos.jar
cos.jar
1. 업로드 전용 라이브러리이다.
2. 파일 첨부 폼 양식은 enctype="multuipart/form-data" 로 설정하는데 이렇게되면 HttpServletRequest를 사용할 수 없다.
3. HttpServletRequest 대신 사용할 MultipartRequest 클래스를 지원하는 라이브러리이다.
[Upload.java]
package ex09_up_down;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
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 com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
/**
* Servlet implementation class Upload
*/
@WebServlet("/upload")
public class Upload extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Upload() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//첨부 파일의 경로
String contentPath="C:/storage";
//첨부 파일이 저장될 디렉터리가 없으면 새로 생성
File dir = new File(contentPath);
if(!dir.exists()) {
dir.mkdirs();
}
//MultipartRequest 객체 생성 (실제 업로드가 진행되는 코드)
MultipartRequest mr=new MultipartRequest(
request, //원래 사용하던 request
contentPath, //파일 첨부 경로
1024*1024*50, //첨부 파일의 최대 크기 (50MB)
"UTF-8", //인코딩
new DefaultFileRenamePolicy()); //첨부 파일명이 중복되는 경우 첨부 파일의 이름을 바꾸는 기본정책(파일명 뒤에 번호를 붙인다.)
//요청 파라미터(HttpServletRequest 대신 MultipartRequest mr 을 이용한다.)
String uploader =mr.getParameter("uploader");
// 첨부 파일
String originName =mr.getOriginalFileName("attach"); //첨부 파일명
String fileSystemName= mr.getFilesystemName("attach"); //저장된 첨부 파일명
File attach=mr.getFile("attach");
String name =attach.getName(); // 저장된 첨부 파일명
String parent= attach.getParent(); // 첨부 파일 저장 디렉터리
String path= attach.getPath(); // 첨부 파일 저장 디렉터리 + 첨부 파일명
String lastModified =new SimpleDateFormat("yyyy-MM-dd").format(attach.lastModified()); //최종 수정일
String size=new DecimalFormat("#,##0").format(attach.length()/1024+(attach.length()%1024==0? 0:1));// byte를 1kb로
//응답
response.setContentType("text/html;charset=UTF-8");
PrintWriter out=response.getWriter();
out.println("<ul>");
out.println("<li>업로더:"+uploader+"</li>");
out.println("<li>첨부 파일명:"+originName+"</li>");
out.println("<li>저장된 첨부 파일명:"+fileSystemName+"</li>");
out.println("<li>저장된 디렉터리:"+parent+"</li>");
out.println("<li>최종 수정일:"+lastModified+"</li>");
out.println("<li>파일 크기:"+size+"KB</li>");
out.println("</ul>");
out.println("<hr>");
//이곳에 첨부된 모든 파일의 목록을 보여주세요
File[] files=dir.listFiles();
for(int i=0;i<files.length;i++)
{
File file=files[i];
out.println("<div><a href=\"/servlet/download?path="+URLEncoder.encode(file.getPath(),"UTF-8") + "\">"+file.getName()+"</a>"+"</div>");
}
out.flush();
out.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
[Download.java]
package ex09_up_down;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLDecoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Download
*/
@WebServlet("/download")
public class Download extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Download() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//요청 인코딩
request.setCharacterEncoding("UTF-8");
//요청 파라미터(다운로드 할 파일명)
String path=URLDecoder.decode(request.getParameter("path"),"UTF-8");
//다운로드 할 파일의 File 객체 생성
File file = new File(path); // new File("C:\storage\404.jpg") //window 기반으로 끼워 맞췃기 때문에 리눅스에서는 동작 안할듯
// 다운로드 할 파일을 읽어 들일 바이트 기반 입력 스트림 생성
BufferedInputStream in=new BufferedInputStream(new FileInputStream(file));
// 다운로드용 응답을 만드려면 응답 헤더에 "Content-Disposition"에 "attachment" 값을 저장해야 한다.
response.setHeader("Content-Disposition", "attachment"); // 다운로드 할 때 파일 저장 대화상자가 나타난다.
response.setHeader("Content-Disposition", "attachment;filename="+path.substring(path.lastIndexOf('\\')+1)); // 다운로드할 때 작성한 filename으로 곧바로 저장된다.
// 바이트 기반 응답 출력 스트림 생성
BufferedOutputStream out= new BufferedOutputStream(response.getOutputStream());
//첨부 파일 읽기 -> byte[] -> 응답 출력 스트림
// in out
// read() write()
byte[]b=new byte[1024]; //1024바이트 단위로 읽기
int readByte=0; // 실제로 읽은 바이트 수
while((readByte=in.read(b))!=-1) //모두 읽어서 더이상 읽은 내용이 없으면 -1이 반환
{ out.write(b,0,readByte); //b를 읽은 바이트 만큼만 내보내기
}
//사용한 스트림 닫기
out.close();
in.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}