본문 바로가기
웹 프로그래밍 기초/자바기반의 웹&앱 응용SW 개발자

자바기반의 웹&앱 응용 SW개발자 양성과정 65일차 -97

by oncerun 2020. 6. 14.
반응형

파일 업로드 비동기식 

window.addEventListener("load", function(){
   
   var editor = document.querySelector(".editor");
   var htmlArea = editor.querySelector(".html-area");
   var boldButton = editor.querySelector(".btn-bold");
   var italicButton = editor.querySelector(".btn-italic");
   var imgButton = editor.querySelector(".btn-img");
   var fileButton = editor.querySelector(".btn-file");
   
   fileButton.oninput = function(e){      
      //상자가 열리고 거기서 파일을 선택하면 상자가 닫힌다.
      // 그럼 현재 선택된 파일의 정보는 어떻게 되는가?
      var files = e.target.files;
      if(files.length > 1){
         alert("파일은 하나만 선택할 수 있습니다.");
         return;
      }
      
      var file = files[0];
      //for(var k in file)
         console.log(file.name + "," + file.type);
      
      //var regEx = new RegExp("image/(jpg|png|gif)");
      //console.log(file.type.match(regEx));
      /*if(file.size > 1024*1024*10){
         alert("너무 파일이 부담되요. 연료부족!!!");
         return;
      }*/
         
      // 아~ 이미지 파일을 하나를 선택했고 이제 그것을 업로드 해야겠다.
      var formData = new FormData();
      formData.append("file", file);
      formData.append("title", "Hello");      
      
      var xhr = new XMLHttpRequest();
      
      xhr.open("POST", "/upload", true);
      xhr.upload.addEventListener("progress", function(e){
         console.log(Math.round(e.loaded*100/e.total)+"%");
      });
      xhr.onload = function(){
         // 선택 영역이라는 것이 있어야만 이미지가 그 위치를 알 수 있고
         // 그래야 삽입이 되는구나.
                  
         htmlArea.focus();
         
         document.execCommand("insertHTML" ,
               false, 
               `<img style="width:200px;" src="/upload/${file.name}" >`);
         
      };
      xhr.send(formData);      
      
         
      
   };
   imgButton.onclick = function(e){      
      e.preventDefault();      
      
      console.log("test");
      //fileButton의 onClick을 트리커하는 코드
      var event = new MouseEvent("click", {
           'view': window,
           'bubbles': true,
           'cancelable': true
       });
       
      fileButton.dispatchEvent(event);
   };
   boldButton.onclick = function(e){      
      e.preventDefault();
      document.execCommand("bold");
   };
   italicButton.onclick = function(e){      
      e.preventDefault();
      document.execCommand("italic");
   };
});

 

 

컨트롤러 처리 부분

package com.newlecture.web.controller;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Collection;

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 org.apache.tiles.TilesContainer;
import org.apache.tiles.access.TilesAccess;

import com.newlecture.web.entity.Notice;
import com.newlecture.web.service.NoticeService;

@MultipartConfig(
   fileSizeThreshold = 1024*1024,   
   maxFileSize = 1000*1024*1024,
   maxRequestSize = 3000*1024*1024
)
@WebServlet("/upload")
public class UploadController extends HttpServlet {
      
   @Override
   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
      String fileNames = "";
      Collection<Part> parts = request.getParts();
      
      for(Part part : parts)
      {
         String a1 = part.getContentType();
         String name = part.getName();
                  
         System.out.printf("type:%s, name:%s", a1, name);
         
         if(!name.equals("file")) continue;
         
         String fileName = ""; 
         // 업로드한 파일 저장하기
         //Part part = request.getPart("file");
         fileName = part.getSubmittedFileName();
         
         // 상대경로->시스템(물리)경로
         String path = request.getServletContext()
                        .getRealPath("/upload");
                
         File file = new File(path);
         if(file.exists())
            file.mkdir();
         
         path += File.separator + fileName;
         System.out.println(path);
         part.write(path);
         fileNames += fileName;
         fileNames += ",";
      }
      fileNames = fileNames.substring(0, fileNames.length()-1);
      //part.getInputStream();
      //part.write(path + fileName);// c:\temp   aa.png
      
      response.getWriter().print(fileNames);
   }
}


 

 

 

 

onreadystatechange가 요청에 대한 응답을 받는 이벤트 리스너입니다.

우리는 xhr.DONE인 즉 요청 완료된 상태에 대해서만 로직을 처리할 것이므로 load이벤트만을 사용했지만

만약 readyState상태마다 각각 로직을 처리해야 한다면 onreadystatechange  요청에 대한 응답을 받는 이벤트 리스너를 사용하면 됩니다.

 AJAX 요청 시 XHR 객체는 각 상태별로 readyState가 바뀝니다.

처음에는 readyState가 0(xhr.UNSENT, 보내지 않음)이었다가,

open 메서드를 호출하는 순간 1(xhr.OPENED)로 바뀝니다.

그리고 send 시 순차적으로 2(xhr.HEADERS_RECEIVED), 3(xhr.LOADING), 4(xhr.DONE)로 바뀝니다.

 

XMLHttpRequest upload 프로퍼티는 업로드 진행 상황을 모니터링할 수 있는 XMLHttpRequestUpload 객체를 반환합니다. 불투명한 객체(opaque object)이지만  XMLHttpRequestEventTarget 이기도 하기 때문에 이벤트 리스너를 연결하여 프로세스를 추적할 수 있습니다.

upload 이벤트에서 다음 이벤트가 트리거 되어 업로드를 모니터링하는 데 사용할 수 있습니다.

Event Event listener Description
loadstart onloadstart 업로드가 시작되었습니다.
progress onprogress 지금까지 진행된 상태를 정기적으로 제공합니다.
abort onabort 업로드가 중단되었습니다.
error onerror 에러로 인해 업로드에 실패했습니다.
load onload 업로드가 성공적으로 완료되었습니다.
timeout ontimeout XMLHttpRequest.timeout에 명시되어 있는 시간 간격 내에 응답이 도착하지 않아, 업로드 시간이 초과되었습니다.
loadend onloadend 업로드가 완료되었습니다. 이 이벤트는 성공과 실패를 구분하지 않고 결과에 관계없이 업로드가 끝나면 전송됩니다. 이 이벤트 발생 이전에는 전송이 종료된 이유를 나타내기 위해 load, error, abort, timeout 중 하나를 전달합니다.
반응형

댓글