투케이2K

13. (spring/스프링) Post Body Form Data 사용해 서버 로컬에 사진 이미지 저장 실시 - post man (포스트맨) 멀티 파트 예시 추가 본문

Spring

13. (spring/스프링) Post Body Form Data 사용해 서버 로컬에 사진 이미지 저장 실시 - post man (포스트맨) 멀티 파트 예시 추가

투케이2K 2021. 7. 15. 17:48

[ 개발 환경 설정 ]

개발 툴 : inteli j

개발 언어 : spring


[ 폴더 및 파일 추가 ]


[소스코드 : controller >> ModuleApiController]

package com.project.solutionpackage.controller;

import org.springframework.boot.configurationprocessor.json.JSONArray;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;

import org.springframework.ui.Model;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

// [rest 방식 컨트롤러 / Controller = view 연결]
@RestController
public class ModuleApiController {

    /**
     * [클래스 설명]
     * 1. thymeleaf 타임리프 view 지정 부분 (html 지정)
     * */


    // [post body form data 방식 : map]
    // [경로 지정 : http://localhost:7000/resourceInsertImage]
    // [body 요청 데이터 : idx = 특정 값 / file = 저장할 파일]
    // [로직 : 사용자 url 호출 및 body 데이터 전송 >> 서버 로컬 pc에 이미지 저장 >> 리턴 데이터 반환]
    @PostMapping("/resourceInsertImage")
    public String resourceInsertImage(
            @RequestParam("idx") String idx,
            @RequestParam("file") MultipartFile files){
        // 사용자는 매개변수에서 지정한 파라미터 명칭에 맞게 key 값으로 넣어야합니다
        System.out.println("\n");
        System.out.println("=======================================");
        System.out.println("[ModuleApiController] : [resourceInsertImage] : [start]");
        System.out.println("[request idx] : " + String.valueOf(idx)); //추가 파라미터
        System.out.println("[request FileName] : " + String.valueOf(files.getOriginalFilename())); //이미지 이름
        System.out.println("[request FilSize] : " + String.valueOf(files.getSize())); //이미지 사이즈
        System.out.println("=======================================");
        System.out.println("\n");

        // [로직 수행 결과 값을 전송할 변수 선언]
        JSONObject result = new JSONObject();

        
        // [서버 로컬에 이미지 저장 로직 수행 실시]
        try {
            // 시스템 os 정보 확인 변수 선언
            String os = System.getProperty("os.name").toLowerCase();

            // 사진을 저장할 폴더 경로 변수 선언
            String folderRoot = "";

            // File 객체 정의
            File file;

            // os 정보 확인 및 사진을 저장할 서버 로컬 경로 지정 실시
            if(os.contains("win")) {
                System.out.println("\n");
                System.out.println("=======================================");
                System.out.println("[ModuleApiController] : [resourceInsertImage] : [os check]");
                System.out.println("[os] : " + "Windows");
                System.out.println("=======================================");
                System.out.println("\n");
                folderRoot = "c:/Home/Resource/assets/"; //윈도우 경로 (디스크 필요)
            }
            else if(os.contains("linux")) {
                System.out.println("\n");
                System.out.println("=======================================");
                System.out.println("[ModuleApiController] : [resourceInsertImage] : [os check]");
                System.out.println("[os] : " + "Linux");
                System.out.println("=======================================");
                System.out.println("\n");
                folderRoot = "/Home/Resource/assets/"; //리눅스 경로
            }
            else {
                System.out.println("\n");
                System.out.println("=======================================");
                System.out.println("[ModuleApiController] : [resourceInsertImage] : [os check]");
                System.out.println("[os] : " + "None");
                System.out.println("=======================================");
                System.out.println("\n");
                // os 확인을 하지 못한 경우 즉시, api 종료
                try {
                    result.put("state", "F");
                    result.put("message", "Not Storage");
                    return result.toString();
                } catch (JSONException jsonException) {
                    jsonException.printStackTrace();
                }
            }

            // 파일 객체 생성 및 폴더 생성 여부 확인 수행
            file = new File(folderRoot);

            if(!file.exists()) { //폴더가 존재하지 않는 경우
                file.mkdirs(); //폴더 생성 수행
                System.out.println("\n");
                System.out.println("=======================================");
                System.out.println("[ModuleApiController] : [resourceInsertImage] : [folder check]");
                System.out.println("[folder] : " + "not exists");
                System.out.println("[folder] : " + "create");
                System.out.println("=======================================");
                System.out.println("\n");
            }
            else { //폴더가 존재하는 경우
                System.out.println("\n");
                System.out.println("=======================================");
                System.out.println("[ModuleApiController] : [resourceInsertImage] : [folder check]");
                System.out.println("[folder] : " + "exists");
                System.out.println("=======================================");
                System.out.println("\n");
            }

            // 파일명에 현재 연도,월,일,시,분,초 + 이미지 파일명 조합 실시 및 서버 로컬에 이미지 저장 수행
            String fileName = getNowTime24() + "_" + String.valueOf(files.getOriginalFilename());
            FileOutputStream fos = new FileOutputStream(folderRoot+fileName);

            byte data[] = files.getBytes();
            InputStream inputStream = files.getInputStream();

            int readCount = 0;
            while ((readCount = inputStream.read(data)) != -1){
                fos.write(data,0, readCount);
            }
            fos.close();
            inputStream.close();

            // 모든 로직 처리가 정상 완료 된 경우
            System.out.println("\n");
            System.out.println("=======================================");
            System.out.println("[ModuleApiController] : [resourceInsertImage] : [image save]");
            System.out.println("[result] : " + "Success");
            System.out.println("[fileRoot] : " + (folderRoot+fileName));
            System.out.println("=======================================");
            System.out.println("\n");
            result.put("state", "T");
            result.put("message", "Success");
        }
        catch (Exception e){
            // 로직 처리 중 예외가 발생한 경우
            System.out.println("\n");
            System.out.println("=======================================");
            System.out.println("[ModuleApiController] : [resourceInsertImage] : [image save]");
            System.out.println("[result] : " + "Fail");
            System.out.println("=======================================");
            System.out.println("\n");
            try {
                result.put("state", "F");
                result.put("message", "Fail");
            } catch (JSONException jsonException) {
                jsonException.printStackTrace();
            }
            e.printStackTrace();
        }
        return result.toString(); //리턴 데이터 반환
    }
    
    // [현재 시간 알아오는 메소드]
    public static String getNowTime24() {
        long time = System.currentTimeMillis();
        //SimpleDateFormat dayTime = new SimpleDateFormat("hh:mm:ss");
        SimpleDateFormat dayTime = new SimpleDateFormat("yyyyMMddkkmmss");
        String str = dayTime.format(new Date(time));
        return "PT"+str; //TODO [PT는 picture 의미]
    }

}

 

[소스코드 : static >> imageUpload.html]

<!DOCTYPE HTML>
<!-- 자바스크립트 차단된 콘텐츠 자동 허용 실시 -->
<!-- saved from url=(0013)about:internet -->

<!-- 표시 언어 지정 -->
<html lang="ko">

<!-- 헤더 정의 부분 -->
<head>
  <title>HTML TEST</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">


  <!-- 내부 CSS 스타일 지정 -->
  <style>

    /* html, body 영역 스타일 지정 */
    html, body{
      width : 100%;
      height : 100%;
      margin : 0;
      padding : 0;
      border : none;

      /* 스크롤바 표시 지정 */
      overflow : auto;
    }



    /* body 스크롤바 메인 스타일 지정 */
    body::-webkit-scrollbar {
      /* 스크롤바 너비 지정 */
      width: 10px;

      /* 스크롤바 배경 색상 지정 */
      background-color: #c1c1c1;
    }
    /* body 스크롤바 thumb 스타일 지정 */
    body::-webkit-scrollbar-thumb {
      /* 스크롤바 thumb 색상 지정 */
      background-color: #444444;
    }



    /* 이미지 레이아웃 스타일 지정 */
    #image-container {
      width : 40%;
      height : 50%;
      margin : 0 auto;
      padding : 0;
      border : 2px solid #000000;
      background-color : #ffffff;
      border-radius : 20px;
      position: relative;
      top: 5%;
      left: 0%;
    }

    #preview-image {
      width : 100%;
      height : 100%;
      margin : 0 auto;
      padding : 0;
      border-radius : 20px;
      position: relative;
      top: 0%;
      left: 0%;
    }



    /* input 레이아웃 스타일 지정 */
    #input-container {
      width : 40%;
      height : 10%;
      margin : 0 auto;
      padding : 0;
      border : none;
      background-color : #ff00ff;
      border-radius : 20px;
      position: relative;
      top: 10%;
      left: 0%;
    }

    #input-file-button {
      width : 100%;
      height : 100%;
      margin : 0 auto;
      padding : 0;

      border-radius : 20px;
      background-color: #FF6600;


      cursor: pointer;


      position: relative;
      top: 0%;
      left: 0%;

      display: table;
    }

    #input-txt {
      color: #ffffff;
      text-align: center;
      font-size: 150%;
      font-weight: bold;

      display: table-cell;
      vertical-align: middle;
    }




    /* delete 레이아웃 스타일 지정 */
    #delete-container {
      width : 40%;
      height : 10%;
      margin : 0 auto;
      padding : 0;
      border : none;
      background-color : #999999;
      border-radius : 20px;
      position: relative;
      top: 13%;
      left: 0%;

      cursor: pointer;
      display: table;
    }

    #delete-txt {
      color: #ffffff;
      text-align: center;
      font-size: 150%;
      font-weight: bold;

      display: table-cell;
      vertical-align: middle;
    }




    /* 서버 로컬 저장 레이아웃 스타일 지정 */
    #server-container {
      width : 40%;
      height : 10%;
      margin : 0 auto;
      padding : 0;
      border : none;
      background-color : #000000;
      border-radius : 20px;
      position: relative;
      top: 16%;
      left: 0%;

      cursor: pointer;
      display: table;
    }

    #server-txt {
      color: #ffffff;
      text-align: center;
      font-size: 150%;
      font-weight: bold;

      display: table-cell;
      vertical-align: middle;
    }


  </style>


  <!-- Jquery CDN 로드 : 항상 최신 버전 사용 -->
  <script src="https://code.jquery.com/jquery-latest.min.js"></script>



  <!-- 내부 JS 지정 -->
  <script>

    /*
    [JS 요약 설명]
    1. window.onload : 웹페이지 로드 완료 상태를 나타냅니다
    2. document.getElementById : 특정 객체 id 를 설정합니다
    3. addEventListener : 특정 객체에 이벤트를 부여합니다
    4. readAsDataURL : 파일을 읽습니다
    5. reader.onload : 파일을 정상적으로 읽은 경우를 나타냅니다
    */


    /* [html 최초 로드 및 이벤트 상시 대기 실시] */
    window.onload = function() {
      console.log("");
      console.log("[window onload] : [start]");
      console.log("");

      // [input 에 이벤트 부여 실시]
      const inputImage = document.getElementById("input-image");
      inputImage.addEventListener("change", readImage, false);
    };



    /* [이미지 불러오기 이벤트 수행 함수] */
    function readImage(evt){
      console.log("");
      console.log("[readImage] : [start]");
      console.log("");

      // 인풋 태그에 파일이 있는 경우
      if(evt.target.files && evt.target.files[0]) {
        console.log("");
        console.log("[readImage] : [reader]");
        console.log("");

        // FileReader 인스턴스 생성
        const reader = new FileReader();

        // 이미지가 로드가 된 경우
        reader.onload = function (e) {
          const previewImage = document.getElementById("preview-image");
          previewImage.src = e.target.result;
          console.log("");
          console.log("[readImage] : [data] : " + previewImage.src);
          console.log("");
        }

        // reader가 이미지 읽도록 하기
        reader.readAsDataURL(evt.target.files[0]);
      }
    };




    /* [삭제 이벤트 수행 함수] */
    function deleteImage(){
      console.log("");
      console.log("[deleteImage] : [start]");
      console.log("");

      // 인풋 태그 src 값이 들어있는지 확인
      const previewImage = document.getElementById("preview-image");
      var data = previewImage.src;
      console.log("");
      console.log("[deleteImage] : [src] : " + data);
      console.log("");

      if(data != "undefined" && data != null && data != ""){
        previewImage.src = "";
      }
    };




    /* [서버 로컬 이미지 업로드 수행 함수] */
    function serverUploadImage(){
      console.log("");
      console.log("[serverUploadImage] : [start]");
      console.log("");

      //필요 전송 데이터 정의 실시
      var url = "http://localhost:7000/resourceInsertImage";
      var inputIdx = "1";

      // 전송 데이터 체크 실시
      console.log("");
      console.log("[serverUploadImage] : [request]");
      console.log("[url] : " + url);
      console.log("[method] : " + "post body form data");
      console.log("[idx] : " + inputIdx);
      console.log(document.getElementById("input-image").files[0]);
      console.log("");

      // input file 에 저장된 파일을 얻어옵니다
      var formData = new FormData();
      formData.append("idx", inputIdx); //추가 파라미터 전송
      formData.append("file", document.getElementById("input-image").files[0]); //실제 파일 데이터 전송

      // post body form data 형식으로 요청
      $.ajax({
        /* 요청 시작 부분 */
        url: url, //주소
        data: formData,
        type: "POST", //전송 타입
        async: true, //비동기 여부
        enctype: "multipart/form-data",
        processData: false, //프로세스 데이터 지정
        contentType: false, //헤더의 Content-Type을 설정

        /* 응답 확인 부분 */
        success: function(response) {
          console.log("");
          console.log("[serverUploadImage] : [response] : " + JSON.stringify(response));
          console.log("");
        },

        /* 에러 확인 부분 */
        error: function(xhr) {
          console.log("");
          console.log("[serverUploadImage] : [error] : " + xhr);
          console.log("");
        },

        /* 완료 확인 부분 */
        complete:function(data,textStatus) {
          console.log("");
          console.log("[serverUploadImage] : [complete] : " + textStatus);
          console.log("");
        }
      });
    };

  </script>

</head>


<body>

<!-- 이미지 레이아웃 -->
<div id="image-container">
  <!-- src 실제로 표시될 이미지 / [초기화] onerror src 에 표시할 이미지가 없을 경우 대체 표시 -->
  <img id="preview-image" src = "">
</div>


<!-- input file 레이아웃 -->
<div id="input-container" for="input-image">
  <!-- input display none 처리 >> label for 사용해 input 지정 후 스타일 커스텀 -->
  <label id="input-file-button" for="input-image"><p id="input-txt">이미지 불러오기</p></label>
  <input id="input-image" type="file" style="display: none">
</div>


<!-- 불러온 이미지 지우기 레이아웃 -->
<div id="delete-container" onclick="deleteImage();">
  <p id="delete-txt">초기화</p>
</div>


<!-- 서버 로컬 저장 레이아웃 -->
<div id="server-container" onclick="serverUploadImage();">
  <p id="server-txt">서버 로컬 저장</p>
</div>

</body>

</html>

[결과 출력]


[포스트맨 사용해 멀티 파트 테스트 방법]


 

반응형
Comments