다연이네

[days11] 파일 업로드 본문

JSP

[days11] 파일 업로드

 다연  2021. 1. 11. 13:54
반응형

 파일 업로드 


1.  게시판, 자료실, 쇼핑몰 등에서 문서 파일이나 이미지 파일 등을 서버에 올리는 작업(업로드)
     서버->클라이언트(다운로드)

2.  실제 파일을 업로드하려면 
     ㄱ.  스트림 기반의 전송 방식인 method="post"로 설정해야 한다.  (규칙)
     ㄴ.  인코딩 방식 설정
     기본값: enctype="application/x-www-form-urlencoded" 설정되어 있는데,
     enctype="multipart/form-data"로 설정해야 한다. 
     ***꼭 기억하자 ㄱ.  ㄴ.  설정 꼭 철자 틀리지 않게 하자
3.  request객체로 getParameter() -> null, null  == request 객체로 파라미터를 사용할 수 없더라
    첨부파일/ 이름 파라미터를 어떻게 처리하는가?


    ㄱ.  개발자가 직접 스트림을 통해서 구현 (잘 안씀) ex02_03_ok. jsp
    
    ㄴ.  서블릿 3. 0 또는 3. 1 이상에서 제공하는 라이브러리 사용 ex03. jsp
        1) HttpServletRequest의 getPart() 메소드를 이용해서 업로드 데이터 접근
            [Part 객체]를 얻어온다
             . getName() :파라미터 이름
             . getContentType() :ContentType
             . getSize() :업로드한 파일 크기
             . getSubmittedFileName() :업로드한 파일명
             . geInputStream() :데이터 읽어옴
             . write() :Part의 업로드 데이터를 파일명이 지정한 파일 복사(파일 실제 쓰기 작업)
             . delete() :생성된 임시 파일을 삭제
             . getHeader() :해당 Part에서 지정한 이름의 헤더 값을 얻어온다. 
        2) 서블릿이 multipart 데이터를 처리할 수 있도록 설정
             ㄱ) web. xml <multipart-config> 설정
             ㄴ) @MultipartConfig 어노테이션을 사용해서 설정
        3) ex03. jsp 여러개의 첨부파일을 서블릿 사용해서 처리
                ex03. jsp + UploadServlet 서블릿
        
    ㄷ.  외부에서 제공하는 라이브러리 사용  ex02_05_ok. jsp


    (우리는 톰캣 8. 5깔다보니 서블릿 3. 0이상이다 그래서 ㄴ. ㄷ.  다 가능)
    1)http://www. servlets. com/ > COS File Upload Library > cos-20. 08. zip 다운
    2) 압축 풀면 lib폴더 안에 cos. jar 파일 존재 => WEB-INF > lib에 저장
    3) 그 jar 파일에서 제공하는 MutipartRequest 클래스 사용해서

       첨부파일, 파라미터 처리
          MutipartRequest mrequest = new MutipartRequest(ㄱ,ㄴ,ㄷ,ㄹ,ㄷ,ㅁ);
          ㄱ - request 객체
          ㄴ - 서버에 저장될 위치(경로)
          ㄷ - 최대 파일 크기
          ㄹ - 파일의 인코딩 방식
          ㅁ - 파일 중복 처리 위한 인자 (클래스)
                a. txt -> 파일 업로드 -> upload폴더 첨부 a. txt
                                                                    a-(1). txt
     4)여러개의 첨부파일 있을 경우 ? 
        ex04. jsp

 

 

ex02.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
</style>
<script>
   $(document).ready(function (){     
   });
</script>
</head>
<body>
<h3>ex02.jsp</h3>
<form action="ex02_02_ok.jsp" method="post"  enctype="multipart/form-data">
	이름: <input type="text" name="name" value="홍길동" /><br>
	첨부파일: <input type="file" name="upload" /><br>
	<input type="submit" />
</form>
</body>
</html>

ex02_02_ok.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
</style>
<script>
   $(document).ready(function (){     
   });
</script>
</head>
<body>
<h3>ex02_02_ok</h3>

<%
	String name= request.getParameter("name");
	String upload= request.getParameter("upload");
%>
>전송된 이름: <%=name %><br>
>전송된 파일: <%=upload %><br>

<!-- 실제 자기PR(2017162029_배다연).hwp 파일이 서버에 업로드 된 것은 아니다.
		단지 파일명만 서버에 submit된 것이다.
		[get 방식]
>전송된 이름: 홍길동
>전송된 파일: 자기PR(2017162029_배다연).hwp

		[post방식 +enctype 설정]
>전송된 이름: null
>전송된 파일: null


 -->
</body>
</html>

pd 

실제 자기PR(2017162029_배다연).hwp 파일이 서버에 업로드 된 것은 아니다.
단지 파일명만 서버에 submit된 것이다.
[get 방식]
>전송된 이름: 홍길동
>전송된 파일: 자기PR(2017162029_배다연).hwp

[post방식 +enctype 설정]
>전송된 이름: null
>전송된 파일: null

 

 

   1.  개발자가 직접 스트림을 통해서 구현 ex02_03_ok. jsp 

<%@page import="java.io.DataInputStream"%>
<%@page import="java.util.Enumeration"%>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%
  Enumeration<String> en = request.getHeaderNames(); 
  out.println(">전송받은 헤더 정보 출력<br>");
  while(en.hasMoreElements()){
	  String key = en.nextElement();
	  String value = request.getHeader(key);
	  out.println(key+" : "+value+"<br>");
  }
%>
<h3>전송받은 데이터 출력</h3>
<%
   ServletInputStream sis = request.getInputStream(); //읽기 용도의 스트림
   DataInputStream dis = new DataInputStream(sis);
   String line = "";
   while( (line= dis.readLine())!=null ){
	   out.println(new String(line.getBytes("ISO-8859-1"), "UTF-8")+"<br>"); //한글 안깨지게
   }
%>

 

<%@page import="java.io.IOException"%>
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%
    ServletInputStream sis = null;
   try{
	  out.print("["+ request.getContentType() +"]"); 
      sis =request.getInputStream();
	  int data = -1;
	  while(   (data = sis.read() ) != -1 ){
		  out.print( (char)data );
	  }
   }catch(Exception e){
	   e.printStackTrace();
   }finally{
	   if( sis!= null){
		   try{
		     sis.close();
		   }catch(IOException e){}
	   }
   }
%>

  ㄱ. boundary=         각각의 파라미터를 구분할 때 사용하는 문자열
  ㄴ. Content-Disposition:   전송되는 파라미터의 name(이름) / 첨부파일 ( 파일명 )
                                         name="upload";                 filename="rhdsetup.log"
  ㄷ. Content-Type:     업로드한 파라미터의 타입                                      
                           Content-Type: application/octet-stream
  ㄹ. \r\n 파라미터값을 전송              

 

        

 

   2. 외부에서 제공하는 라이브러리 사용  ex02_05_ok. jsp 

<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.multipart.FileRenamePolicy"%>
<%@page import="java.io.File"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!--  ex02_05_ok.jsp -->

<%
 //request는 사용하지 않는다 (null찍히니까)
 //cos.jar 파일이 추가되어있는지 꼭 확인 (WEB-INF > lib)
 //서버에 저장할 곳 : String saveDirectory 
 String saveDirectory = pageContext.getServletContext().getRealPath("/days11/cos/upload");
System.out.println(saveDirectory);
File saveDir = new File(saveDirectory);
if(!saveDir.exists()) saveDir.mkdirs(); //폴더 없으면 해당 하위폴더까지 다 만들라고 ( cos/upload 폴더 유무 확인 후 생성)

//기본단위 byte ->  5MB 저장가능하도록 설정하겠다
int maxPostSize =  5*1024*1024; //5MB
String encoding = "UTF-8";

FileRenamePolicy policy = new DefaultFileRenamePolicy(); //자동으로 파일명-1(인덱스) 붙히게 해줌


 MultipartRequest mrequest = new MultipartRequest( //인자5개
		 request
		 , saveDirectory
		 , maxPostSize
		 , encoding 
		 , policy
		 );
 	// mrequest 객체 예외 발생하지 않고 생성이 되었다면 첨부된 파일은 벌써 업로드가 완료했다.
 	//아무것도 안해도 이 객체가 자동으로 만들어지면 첨부파일은 내가 지정한 경로에 업로드 되어진 것
 	
 	//나는 뭐하면돼? 파라미터 값(첨부된 파일명)을 db에 저장
 	//(지금은) 파라미터를 출력해서 확인
 	String name=  mrequest.getParameter("name");
 	File uploadFile = mrequest.getFile("upload"); //input태그의 name 속성값
 	//첨부파일 여러개면 반복하며 여러개 달면 됨
 	//mrequest.getFile("upload"); 이렇게 for문 주던지 while 주던지
 	
 	//출력
 	//ㄱ. 첨부파일명
 	String fileName = uploadFile.getName();
 	//ㄴ. 첨부파일 크기
 	long fileLength = uploadFile.length();
 	//ㄱ.ㄴ.은 파일 객체에 있는 것 (자바할 때 처럼)
 	
 	//*** 만약 첨부파일(a.txt)을 업로드   -> cos/upload 폴더에 저장하는데 원래 a.txt가 있어
 	//그럼 새로 올라가는 애는 a-1.txt로 인덱스가 붙어 실제 올라가
 	//그럼 우리가 올리고자 했던 애(a.txt)는 오리지날, 
 	//실제 올라간 a-1.txt 모두 디비에 저장해야 함
 	String originalFileName = mrequest.getOriginalFileName("upload"); //올릴때 이름
 	String filesystemName = mrequest.getFilesystemName("upload");//올라간 이름
%>

>전송된 이름: <%=name%><br>
>첨부된 파일명: <%=fileName%><br>
>첨부된 파일 크기: <%=fileLength%><br>
>오리지널 파일명: <%=originalFileName%><br>
>실제 저장돤 파일명: <%=filesystemName%><br>

똑같은 파일을 한 번 더 올리면 ?

자동으로 인덱스가 붙어서 올라가는데, db에는 원래 파일명과 바뀐 파일명 모두 저장시켜한다.

 

 

파일은 위치에 잘 올라가 있다!

위치 : C:\Class\JSPClass\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\jspPro\days11\cos\upload

cos 폴더와 upload 폴더가 없어도 생성해서 올라가있다.

 

2-2.  외부 라이브러리로 여러 첨부 파일 처리하는 예제

ex04.jsp

<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SS13 - k≡n¡k ( 2021. 1. 11 - t오전 10:41:33 )</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
</style>
<script>
   $(document).ready(function (){	  
	   $("button").on("click", function(event) {
	   	  var n = $("#demo :file").length + 1;
	   	  $("#demo").append(  "첨부 파일 "+n+" : <input type='file' name='file"+n+"'><br>");
	   });//  click
	   
   }); // ready
</script>
</head>
<body>
 <h3>ex04.jsp</h3>
 <!-- cos.jar 외부 라이브러리로 여러 첨부 파일 처리하는 예제. -->
 <!-- ex02_05_ok.jsp 복사 붙이기 ex04_02_ok.jsp -->
 <form action="ex04_02_ok.jsp" 
 method="post"
 enctype="multipart/form-data"
 >
 
 message : <input type="text" name="msg" value="hello world~" /><br>
 <button type="button">첨부 파일 추가</button>
 <div id="demo">
  첨부 파일 1 : <input type="file" name="file1"><br>
 </div>
 <input type="submit" value="전송" />
 
 </form>
</body>
</html>

ex04_02_ok.jsp

<%@page import="java.util.Enumeration"%>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="java.io.File"%>

<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@page import="com.oreilly.servlet.multipart.FileRenamePolicy"%>

<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- ex04_02_ok.jsp -->
<%
   
    String saveDirectory = pageContext.getServletContext().getRealPath("/days11/cos/upload");
    System.out.println( saveDirectory );
    // cos/upload 폴더 유무 확인 후 생성
    File saveDir = new File( saveDirectory );
    if( !saveDir.exists() ) saveDir.mkdirs();
    
    // 기본단위 byte    
    int maxPostSize = 5 * 1024 * 1024 ; // 5MB    
    String encoding = "UTF-8";
    
    FileRenamePolicy policy = new DefaultFileRenamePolicy();  //  Setup1.log
    
    MultipartRequest mrequest = new MultipartRequest(
    		request
            ,  saveDirectory 		
    		,  maxPostSize
    		, encoding
    		, policy
    		);
   // ***
   // mrequest 객체 예외 발생하지 않고 생성이 되었다면 
   //  여러 개의 첨부된 파일은 벌써 업로드가 자동으로 완료했다.
   
   // 화면 파라미터를 출력해서 확인
   String msg =  mrequest.getParameter("msg");
 %>
 > 전송된 메시지 : <%= msg %><br>
 <hr>
 <%
  Enumeration  en =  mrequest.getFileNames();
  
  while( en.hasMoreElements() ){
	  String name = (String) en.nextElement();
	  File uploadFile = mrequest.getFile(name); 
	   String fileName = uploadFile.getName(); 
	   long fileLength = uploadFile.length(); 
	   String originalFileName = mrequest.getOriginalFileName(name);
	   String filesystemName = mrequest.getFilesystemName(name);
%>
> 첨부된 파일명 : <%= fileName %><br>
> 첨부된 파일크기 : <%= fileLength %><br>
> 오리지널 파일명 : <%= originalFileName %><br>
> 실제 저장된 파일명 : <%= filesystemName %><br>
<hr>
<%	   
  }
%>

 

 

 

    3.  서블릿 3. 0 또는 3. 1 이상에서 제공하는 라이브러리 사용 ex03. jsp 

ex03.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="">
<style>
</style>
<script>
   $(document).ready(function (){     
	   $("button").on("click", function(event) {
	   	var n = $("#demo :file").length+1;
	   	$("#demo").append( "첨부파일"+n+": <input type='file' name='file"+n+"' /><br>");
	   }); //click
	   
   });//ready
</script>
</head>
<body>
<h3>ex03.jsp</h3>
 <!-- 서블릿 3.0 또는 3.1 이상에서 제공하는 라이브러리 사용 ex03.jsp -->
 <form action="/jspPro/days11/upload" method="post" enctype="multipart/form-data">
   message: <input type="text" name="msg" value="hello world~" /><br>
   <button type="button">첨부 파일 추가</button>
   <div id="demo">
     첨부파일 1: <input type="file" name="file1" /><br>
   </div>
   <input type="submit" value="전송" />
   
 </form>
</body>
</html>

원하는 만큼 추가 가능

 

 

UploadServlet.java

package days11;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.Part;



//@WebServlet("/days11/upload")
public class UploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    
    public UploadServlet() {
        super();
    }

	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
	         throws ServletException, IOException { 
	     // request.setCharacterEncoding("utf-8"); 필터
	      response.setContentType("text/html; charset=utf-8");

	      PrintWriter writer = response.getWriter();
	      writer.println("<html><body>");

	      String contentType = request.getContentType();
	      //                                                                              첨부파일 존재
	      if (contentType != null && contentType.toLowerCase().startsWith("multipart/")) {
	         printPartInfo(request, writer); //함수호출
	      } else {
	         writer.println("multipart가 아님");
	      }
	      writer.println("</body></html>");
	   }

     	//사용자 정의 함수
	   private void printPartInfo(HttpServletRequest request, PrintWriter writer)
	         throws IOException, ServletException {
		   
		   //첨부파일이 여러개일 경우 request.getParts()메소드로 Part객체를 컬렉션으로 얻어온다.
	      Collection<Part> parts = request.getParts();
	      
	      for (Part part : parts) {
	         
	         writer.println("<br/> name = " + part.getName()); // 파라미터 이름
	         String contentType = part.getContentType();           // 컨텐츠 타입
	         writer.println("<br/> contentType = " + contentType);
	         
	         //                                                                          첨부된 파일명
	         if (part.getHeader("Content-Disposition").contains("filename=")) {
	            
	            writer.println("<br/> size = " + part.getSize());
	            String fileName = part.getSubmittedFileName(); // 업로드 파일 이름
	            writer.println("<br/> filename = " + fileName);
	            if (part.getSize() > 0) {                               // 업로드 파일 크기
	               part.write("c:\\temp\\" + fileName);          // 업로드한 파일을 지정한 파일에 복사
	               part.delete();                                           // 임시 파일 삭제
	            }
	            
	         } else {
	            String value = request.getParameter(part.getName());
	            writer.println("<br/> value = " + value);
	         }
	         writer.println("<hr/>");
	      } // for
	      //C:\Temp에 올린 파일들 다 올라가 있음
	      //1024보다 크면 임시파일에 저장되고 복사된 후 삭제
	      //화면에 찍힌 파일들은 db에 insert하면 됨
	   } // method

}

web.xml

<servlet>
     <servlet-name>UploadServlet</servlet-name>
     <servlet-class>days11.UploadServlet</servlet-class>
     <multipart-config>
       <location>C:\apache-tomcat-8.5.60\uploadTemp</location> 
       <!-- c드라이브 톰캣 안에 uploadTemp라는 폴더 만들어 둠 -임시파일 저장공간  -->
       <max-file-size>-1</max-file-size>
       <!-- 업로드 가능한 최대 파일 크기(byte) (-1:제한없음)  -->
       <max-request-size>-1</max-request-size>
       <!-- 전체 multipart 요청 데이터의 최대 제한 크기 (byte) (-1:제한없음) -->
       <!-- 프로젝트시 제한없음 두면 문제생기니 정책적으로 정해두기 -->
       <file-size-threshold>1024</file-size-threshold> 
       <!-- 업로드한 파일의 크기가 1024bytes보다 작으면 메모리에 파일을 임시로 보관, 
                                                 크면 location 설정 폴더에 임시 파일 생성 보관-->
     </multipart-config>
  </servlet>
  <servlet-mapping>
     <servlet-name>UploadServlet</servlet-name>
     <url-pattern>/days11/upload</url-pattern>
  </servlet-mapping>
  

C:Temp 위치에 파일 업로드 되어있음
임시 파일 저장 공간

파일 크기가 1024bytes보다 크면 임시파일 저장공간에 먼저 생성된 후 C:Temp에 생성 완료 되면 임시파일 저장공간에 있던 파일들이 삭제된다.

임시 파일 저장 공간 경로는 C:\apache-tomcat-8.5.60\uploadTemp 이다.

반응형
Comments