본문 바로가기
PROGRAMING📚/Spring📑

서버 사이드 랜더링 방식

Ta이니 2024. 9. 29.
728x90
반응형

서버사이드 랜더링 방식 사용

//쿼리메서드나, deleteById등은 한건씩 진행을 한다
  //@Query 를 사용해서 update,delete 할 경우에 사용 Bulk 연선을 함
  //그래서 트랜젝션을 복수개 할 것을 한번에 처리하기 때문에
  //복수의 트랜잭션으 한번에 처리하기 위해 @Modifying을 사용
  @Modifying
  @Query("delete from Review r where r.member = :member")
  void deleteByMember(Member member);

application.properties의 역할은 프로젝트의 초기화와 같은 역할을 한다

# App name
spring.application.name=ex6

# Server port
server.port=8080

# Context path
server.servlet.context-path=/ex6

# Restart WAS
spring.devtools.livereload.enabled=true

# Spring Datasource
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/db7
spring.datasource.username=db7
spring.datasource.password=1234

# JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.show-sql=true

# Thymeleaf
spring.thymeleaf.cache=false

#File upload setting for Application
com.example.upload.path=c:\\upload

파일 업로드를 하기 위한 라이브러리를 추가해줌

#File upload setting for Application
com.example.upload.path=c:\\upload

용량이 크기 떄문에 @PostMapping 을 사용

HTTP POST 요청을 처리하기 위해 사용됩니다. Spring MVC에서 컨트롤러 메서드를 특정 URL 경로에 매핑하고, 해당 경로로 들어오는 POST 요청을 처리할 수 있도록 합니다. 주로 폼 데이터를 서버로 전송하거나, 서버에 자원을 생성할 때 사용됩니다

  • @RestController는 해당 클래스가 RESTful 웹 서비스의 컨트롤러임을 나타냅니다.
  • @RequestMapping("/api")는 이 컨트롤러의 모든 요청이 /api 경로로 시작됨을 지정합니다.
  • @PostMapping("/create")/api/create 경로로 들어오는 POST 요청을 create 메서드에 매핑합니다.
  • @RequestBody는 요청 본문(body)에 담긴 JSON이나 XML 데이터를 Java 객체로 변환하여 메서드의 매개변수로 전달합니다.

MultipartFile은 파일 업로드를 처리하기 위해 제공되는 인터페이스입니다. MultipartFile을 사용하면 클라이언트가 전송한 파일을 서버에서 손쉽게 다룰 수 있습니다. 여기서 MultipartFile은 주로 Spring MVC나 Spring Boot에서 파일 업로드 기능을 구현할 때 사용됩니다.

기본 개념

  • MultipartFile 인터페이스: 파일의 메타데이터(파일 이름, 콘텐츠 유형 등)와 파일 데이터(파일의 바이트 배열)를 다룰 수 있는 방법을 제공합니다.
  • MultipartFile의 주요 메소드:
    • getName(): 파일의 파라미터 이름을 반환합니다.
    • getOriginalFilename(): 업로드된 파일의 원래 이름을 반환합니다.
    • getContentType(): 파일의 MIME 타입을 반환합니다.
    • getBytes(): 파일의 내용을 바이트 배열로 반환합니다.
    • getInputStream(): 파일의 내용을 InputStream으로 반환합니다.
    • transferTo(File dest): 파일을 지정된 위치로 저장합니다.
@RestController
@Log4j2
public class UploadController {

  @PostMapping("/uploadAjax")
  public  void upload(MultipartFile[] uploadFiles){

  }
}

파일 업로드 컨트롤러

  //파일을 업로드
  @PostMapping("/uploadAjax")
  public  void upload(MultipartFile[] uploadFiles){
    for(MultipartFile multipartFile: uploadFiles){
      String originalName = multipartFile.getOriginalFilename();
      String fileName = originalName.substring(originalName.lastIndexOf("\\")+1);
      log.info("fileName: "+fileName);
    }
  }

multiple 하나의 파일이 아닌 여러개의 파일을 올릴 수 있게 해줌

<input type="file" name="uploadFiles" multiple>

Axios는 JavaScript에서 HTTP 요청을 쉽게 수행할 수 있도록 도와주는 인기 있는 라이브러리입니다.

주로 웹 애플리케이션에서 클라이언트와 서버 간의 통신을 관리하는 데 사용됩니다.

이는 브라우저나 Node.js 환경에서 모두 사용할 수 있으며, 비동기적 HTTP 요청을 지원합니다.

axios 를 사용하는 방법

<scirpt src="http://unpkg.con/axios/dist/axios.min.js"></scirpt>
  • Axios의 주요 역할과 기능
    • HTTP 요청 처리:
      • Axios는 GET, POST, PUT, DELETE 등 다양한 HTTP 메서드를 통해 서버와 데이터를 주고받을 수 있습니다. 예를 들어, 서버에서 데이터를 가져오거나(Form 데이터 전송, JSON 데이터 송수신 등) 서버에 데이터를 보낼 수 있습니다.
    • Promise 기반:
      • Axios는 Promise API를 기반으로 하여 비동기적으로 요청을 처리합니다. 이로 인해 요청 성공 시 .then() 메서드를, 실패 시 .catch() 메서드를 사용하여 응답을 처리할 수 있습니다. 이는 비동기 작업의 결과를 쉽게 다룰 수 있도록 해줍니다.
    • 자동 JSON 데이터 변환:
      • Axios는 요청 시 보내는 데이터와 응답으로 받는 데이터를 자동으로 JSON으로 변환해줍니다. 이를 통해 데이터 직렬화 및 역직렬화 작업을 간단하게 처리할 수 있습니다.
    • HTTP 요청/응답 인터셉터:
      • Axios는 요청과 응답을 가로채서 공통 작업(예: 인증 헤더 추가, 로딩 상태 표시 등)을 처리할 수 있는 인터셉터(interceptors)를 제공합니다. 이를 통해 모든 요청이나 응답에 대해 공통 작업을 처리할 수 있습니다.
    • 요청 취소:
      • Axios는 요청을 취소할 수 있는 기능을 제공합니다. 이는 특정 조건에 따라 불필요한 요청을 취소하고, 자원 사용을 절약할 수 있습니다.
    • 타임아웃 설정:
      • Axios는 각 요청에 대해 타임아웃을 설정할 수 있습니다. 요청이 지정된 시간 내에 완료되지 않으면 요청이 자동으로 취소됩니다.
    • 기본 URL 및 헤더 설정:
      • Axios 인스턴스를 생성할 때 기본 URL 및 공통으로 사용될 헤더를 설정할 수 있습니다. 이를 통해 각 요청마다 반복되는 설정을 줄일 수 있습니다.
      // Axios 라이브러리 불러오기
      import axios from 'axios';
      
      // GET 요청 예시
      axios.get('https://api.example.com/data')
      .then(response => {
        console.log(response.data); // 요청 성공 시 처리
      })
      .catch(error => {
        console.error('Error:', error); // 요청 실패 시 처리
      });
      
      // POST 요청 예시
      axios.post('https://api.example.com/data', {
      name: 'John Doe',
      age: 30
      })
      .then(response => {
        console.log(response.data); // 요청 성공 시 처리
      })
      .catch(error => {
        console.error('Error:', error); // 요청 실패 시 처리
      });
      

폼을 생성하는 방법

var formData = new FormData();

속성 선택자를 사용해서 inputfiles 안에 해당하는 속성의 타입

const inputFiles = document.querySelector("input[type='file']");

var files = inputFiles.files;

<script th:inline="javascript">
  document.querySelector(".uploadBtn").onclick= function(){
    var formData = new FormData();
    const inputFiles = document.querySelector("input[type='file']");
    var files = inputFiles.files;
    for(let i=0; i<files.length; i++){
      console.log(files[i])
      formData.append("uploadFiles", files[i]);
    }
    const url = /*[[@{/uploadAjax}]]*/'url'
  }
</script>

파일 여러개 선택하고 upload 하면 다음과 같이 console 안에 출력됨

window.onload를 사용하는 이유

  1. 전체 페이지 로드 보장:
    • window.onload는 페이지의 모든 콘텐츠가 로드된 후에만 실행됩니다. 따라서 이미지를 포함한 모든 리소스가 준비된 이후에 특정 작업을 수행할 수 있습니다.
  2. DOM 조작 시 안정성 보장:
    • JavaScript를 사용하여 DOM(Document Object Model)을 조작할 때, DOM이 완전히 구성되기 전에 코드를 실행하면 오류가 발생할 수 있습니다. window.onload를 사용하면 이러한 오류를 방지할 수 있습니다.
  3. 초기화 작업 수행:
    • 웹 애플리케이션의 초기화 작업(예: 초기 데이터 로드, 이벤트 리스너 등록 등)을 페이지가 완전히 로드된 후에 수행해야 하는 경우에 유용합니다.
<script th:inline="javascript">
  window.onload = function(){
    document.querySelector(".uploadBtn").onclick = function() {
      var formData = new FormData();
      const inputFiles = document.querySelector("input[type='file']");
      var files = inputFiles.files;
      for(let i=0;i<files.length;i++){
        console.log(files[i])
        formData.append("uploadFiles", files[i]);
      }
      const url = /*[[@{/uploadAjax}]]*/'url'
    }
  }
</script>

Spring Framework의 Thymeleaf 템플릿 엔진

const url = /*[[@{/uploadAjax}]]*/'url';
  1. /*[[@{/uploadAjax}]]*/:
    • 이 부분은 Thymeleaf에서 사용되는 표현식으로, 주석 안에 포함된 텍스트가 서버 측에서 처리됩니다.
    • @{...}은 Thymeleaf의 URL 표기법으로, URL을 동적으로 생성하기 위해 사용됩니다. {} 안에 지정된 경로는 애플리케이션의 컨텍스트 경로를 포함하여 올바른 URL로 변환됩니다.
    • /uploadAjax는 애플리케이션 내의 특정 경로를 나타내며, 이 경로에 해당하는 실제 URL이 생성됩니다.
  2. 'url':
    • 'url'은 JavaScript의 문자열로, 실제 URL이 Thymeleaf에 의해 동적으로 생성된 후 대체될 문자열입니다.

동작 방식

  • 서버 측에서 Thymeleaf 템플릿을 렌더링할 때, /*[[@{/uploadAjax}]]*/ 구문이 실행됩니다.
  • 이 구문은 현재 애플리케이션의 컨텍스트 경로와 결합하여 /uploadAjax에 대한 완전한 URL을 생성합니다.
  • 생성된 URL은 'url'이라는 기본 문자열을 대체합니다.

axios 파일을 업로드 하기 위해서는 다음 코드를 작성해야함

axios.post(url, formData, {
        headers: {
        "Content-Type" : "multipart/form-data",
        "Access-Control-Allow-Origin" : "*",
        "process-data" : false,
        "content-type" : false,
        }
      })
      .then(res => {console.log(res.data)})
      .catch(err=> console.log("Error occourred: ",err))

src/main/resources/templates/uploadEx.html

더보기
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<input type="file" name="uploadFiles" multiple>
<button class="uploadBtn">Upload</button>
<div class="uploadResult"></div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script th:inline="javascript">
  window.onload = function(){
    document.querySelector(".uploadBtn").onclick = function() {
      var formData = new FormData();
      const inputFiles = document.querySelector("input[type='file']");
      var files = inputFiles.files;
      for(let i=0;i<files.length;i++){
        console.log(files[i])
        formData.append("uploadFiles", files[i]);
      }
      const url = /*[[@{/uploadAjax}]]*/'url'
      axios.post(url, formData, {
        headers: {
        "Content-Type" : "multipart/form-data",
        "Access-Control-Allow-Origin" : "*",
        "process-data" : false,
        "content-type" : false,
        }
      })
      .then(res => {console.log(res.data)})
      .catch(err=> console.log("Error occourred: ",err))
    }
  }
</script>

</body>
</html>

@Value("${com.example.upload.path}")

@RestController
@Log4j2
public class UploadController {
  @Value("${com.example.upload.path}")
  private  String uploadPath;
  //파일을 업로드
  @PostMapping("/uploadAjax")
  public  void upload(MultipartFile[] uploadFiles){
    for(MultipartFile multipartFile: uploadFiles){
      String originalName = multipartFile.getOriginalFilename();
      String fileName = originalName.substring(originalName.lastIndexOf("\\")+1);
      log.info("fileName: "+fileName);
    }
  }
}
//src/main/resources/application.properties
#File upload setting for Application
com.example.upload.path=c:\\upload
axios.post(url, formData, {
        headers: {
        "Content-Type" : "multipart/form-data",
        "Access-Control-Allow-Origin" : "*",
        "process-data" : false,
        "content-type" : false,
        }
      })
      .then(res => {console.log(res.data)})
      .catch(err=> console.log("Error occourred: ",err))

 

upload 하면 axios가 서버에 데이터를 보내, 콘솔에서도 콘솔에서 확인 가능

 

fetch(url, {
        method: 'POST',
        body: formData,
        dataType: 'json',
      })
      .then(res => res.json())
      .then(json => {console.log(json);})
      .catch(err => console.log("Error occourred: ",err))

파일을 업로드하고 저장하기 위해서 다음과 같이 코드 작성

@Value("${com.example.upload.path}")

private String uploadPath; 는 c:/upload 가 들어감

파일이 존재하진 않으면 폴더를 생성하고 있는경우 폴더를 생성하지 않게 만들어줌

 private String makeFolder(){
    String str = LocalDate.now().format(DateTimeFormatter.ofPattern("yyy/MM/dd"));
    String folderPath = str.replace("/", File.separator);
    File uploadPathFolder = new File(uploadPath, folderPath);
    if(!uploadPathFolder.exists()){
      uploadPathFolder.mkdirs(); //폴더 만듬
    }
    return folderPath;
  }
  @PostMapping("/uploadAjax")
  public  void upload(MultipartFile[] uploadFiles){
    for(MultipartFile multipartFile: uploadFiles){
      String originalName = multipartFile.getOriginalFilename();
      String fileName = originalName.substring(originalName.lastIndexOf("\\")+1);
      log.info("fileName: "+fileName);
            //추가
      String folderPath = makeFolder();
      String uuid = UUID.randomUUID().toString();
      String savaName = uploadPath+File.separator+folderPath+File.separator
          + uuid+"_"+fileName;
      Path savePath = Paths.get(savaName);
      try {
        multipartFile.transferTo(savePath);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

이미지를 올려주고 그거에 대해서 db에 정보를 저장해주는 방법UploadResultDTO 생성

@Data
@AllArgsConstructor

public class UploadResultDTO implements Serializable {
  private String fileName; 
  private String uuid;
  private String folderPath;

  public String getImageURL(){
    try {
        //파일명에 한글이 쓰이는경우 처리
      return URLEncoder.encode(folderPath+"/"+uuid+"_"+fileName, "UTF-8"); 

    } catch (UnsupportedEncodingException e){
      e.printStackTrace();
    }
    return "";
  }

ResponseEntity는 Spring Framework에서 제공하는 클래스로, HTTP 응답의 전체를 나타내는 데 사용됩니다. 이는 응답 상태 코드, 헤더, 바디 등을 모두 포함할 수 있는 컨테이너 역할을 합니다. Spring MVC에서 컨트롤러 메서드의 반환 타입으로 자주 사용되며, 클라이언트에게 더 많은 정보를 명확하고 유연하게 전달할 수 있게 해줍니다.

주요 기능과 특징

  1. 상태 코드(Status Code):
    • ResponseEntity는 HTTP 상태 코드를 포함할 수 있습니다. 예를 들어, 성공적인 요청의 경우 200(OK), 리소스가 생성된 경우 201(Created), 클라이언트 오류인 경우 400(Bad Request) 등을 설정할 수 있습니다.
  2. 응답 헤더(Response Headers):
    • 응답에 포함될 HTTP 헤더를 설정할 수 있습니다. 예를 들어, Content-Type, Cache-Control, Set-Cookie 등의 헤더를 설정할 수 있습니다.
  3. 응답 본문(Response Body):
    • 응답의 본문 데이터를 포함할 수 있습니다. 이는 일반적으로 JSON 또는 XML 형태의 데이터로, 클라이언트가 필요로 하는 실제 정보를 담고 있습니다.
 //src/main/java/com/example/ex6/controller/UploadController.java
 @PostMapping("/uploadAjax")
 public ResponseEntity<List<UploadResultDTO>> upload(MultipartFile[] uploadFiles){
   List<UploadResultDTO> resultDTOList = new ArrayList<>();
   ....
     String folderPath = makeFolder();
      String uuid = UUID.randomUUID().toString();
      String saveName = uploadPath + File.separator + folderPath + File.separator
          + uuid + "_" + fileName;
      Path savePath = Paths.get(saveName);
      try {
        multipartFile.transferTo(savePath);
        resultDTOList.add(new UploadResultDTO(fileName, uuid, folderPath));
      } catch (IOException e) {
        log.error(e.getMessage());
        return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
      }
    return new ResponseEntity<>(resultDTOList, HttpStatus.OK);
  }
script th:inline="javascript">
  window.onload = function(){
    document.querySelector(".uploadBtn").onclick = function() {
      var formData = new FormData();
      const inputFiles = document.querySelector("input[type='file']");
      var files = inputFiles.files;
      for(let i=0;i<files.length;i++){
        console.log(files[i])
        formData.append("uploadFiles", files[i]);
      }
      const url = /*[[@{/uploadAjax}]]*/'url'
      fetch(url, {
        method: 'POST',
        body: formData,
        dataType: 'json',
      })
      .then(res => res.json())
      .then(json => {console.log(json);showUploadedImages(json)})
      .catch(err => console.log("Error occurred: ", err))

    }
  }
  function showUploadedImages(arr) {
    const uploadResultDiv = document.querySelector(".uploadResult")
    let str = ""
    for(let i=0;i<arr.length;i++){
      str += `<img src="/display?fileName=${arr[i]}">`
    }
    uploadResultDiv.innerHTML = str;
  }
</script>
  function showUploadedImages(arr) {
    const uploadResultDiv = document.querySelector(".uploadResult")
    let str = ""
    for(let i=0;i<arr.length;i++){
      str += `<img src="/display?fileName=${arr[i]}">`
    }
    uploadResultDiv.innerHTML = str;
  }

이미지가 바이너리 파일이라서 byte 타입으로 파일이름과 사이즈를 받아온다

@GetMapping("/display")
  public ResponseEntity<byte[]> getImageFile(String fileName, String size) {
    ResponseEntity<byte[]> result = null;
    try {
      String searchFilename = URLDecoder.decode(fileName, "UTF-8");
      File file = new File(uploadPath + File.separator + searchFilename);
      if (size != null && size.equals("1")) {
        log.info(">>",file.getName());
        file = new File(file.getParent(), file.getName().substring(2));
      }
      log.info("file: " + file);
      HttpHeaders headers = new HttpHeaders();
      // 파일의 확장자에 따라서 브라우저에 전송하는 MIME타입을 결정
      headers.add("Content-Type", Files.probeContentType(file.toPath()));
      result = new ResponseEntity<>(
          FileCopyUtils.copyToByteArray(file), headers, HttpStatus.OK);
    } catch (Exception e) {
      log.error(e.getMessage());
      return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
    }
    return result;
  }
  @PostMapping("/uploadAjax")
  public ResponseEntity<List<UploadResultDTO>> upload(MultipartFile[] uploadFiles) {
    List<UploadResultDTO> resultDTOList = new ArrayList<>();

    for (MultipartFile multipartFile : uploadFiles) {
      String originalName = multipartFile.getOriginalFilename();
      String fileName = originalName.substring(originalName.lastIndexOf("\\") + 1);
      log.info("fileName: " + fileName);

      String folderPath = makeFolder();
      String uuid = UUID.randomUUID().toString();
      String saveName = uploadPath + File.separator + folderPath + File.separator
          + uuid + "_" + fileName;
      Path savePath = Paths.get(saveName);
      try {
        multipartFile.transferTo(savePath); //원본파일 저장
        //추가
        String thumbnailSaveName = uploadPath+File.separator+folderPath+File.separator
            + "s_"+uuid+"_"+fileName;
        File thumbnailFile = new File(thumbnailSaveName);
        Thumbnailator.createThumbnail(savePath.toFile(), thumbnailFile,100,100);
        resultDTOList.add(new UploadResultDTO(fileName, uuid, folderPath));
      } catch (IOException e) {
        log.error(e.getMessage());
        return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
      }
    }
    return new ResponseEntity<>(resultDTOList, HttpStatus.OK);
  }

 


삭제하기

  @PostMapping("/removeFile")
  public ResponseEntity<Boolean> removeFile(String fileName) {
    String searchFilename = null;
    try {
      searchFilename = URLDecoder.decode(fileName, "UTF-8");
      File file = new File(uploadPath + File.separator + searchFilename);
      boolean result1 = file.delete();
      File thumbnail =
          new File(file.getPath() + File.separator + "s_" + searchFilename);
      boolean result2 = thumbnail.delete();
      return new ResponseEntity<>(
          (result1 && result2) ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR
      );
    } catch (Exception e) {
      log.error(e.getMessage());
      return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

영화에 대한 영화번호, 영화제목에 대한 정보를 전달 해주기 위해서 movieDTO 를 생성

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MovieDTO {
  private Long mno;
  private String title;

  @Builder.Default //속성의 기본값으로 초기화
  private List<MovieImageDTO> imageDTOList = new ArrayList<>();

  private double avg;
  private int reviewCnt;

  private LocalDateTime regDate;
  private LocalDateTime modDate;
}

@Builder.Default 생성시 속성의 기본값 초기화 ,@AllArgsConstructor 가 없으면 에러 발생

영화 이미지에 대한 정보를 전달하기 위한 MovieImageDTO 를 생성

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MovieImageDTO {
  private String uuid;
  private String imgName;
  private String path;

  public String getImageURL() {
    try {
      return URLEncoder.encode(path + "/" + uuid + "_" + imgName,
          "UTF-8");
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    return "";
  }

  public String getThumbnailURL() {
    try {
      return URLEncoder.encode(path + "/s_" + uuid + "_" + imgName, "UTF-8");
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    return "";
  }
}

MovieService 구현하기

dto → entity / entity →dto 로 바꿔주는 함수 구현해줌

public interface MovieService {
  Long register(MovieDTO movieDTO);
  //
  default Map<String, Object> dtoToEntity(MovieDTO movieDTO){
    Map<String, Object> entityMap = new HashMap<>();
    Movie movie = Movie.builder().mno(movieDTO.getMno())
        .title(movieDTO.getTitle()).build();
    entityMap.put("movie", movie);
    List<MovieImageDTO> imageDTOList = movieDTO.getImageDTOList();
    if (imageDTOList != null && imageDTOList.size() > 0) {
      List<MovieImage> movieImageList = imageDTOList.stream().map(
          new Function<MovieImageDTO, MovieImage>() {
            @Override
            public MovieImage apply(MovieImageDTO movieImageDTO) {
              MovieImage movieImage = MovieImage.builder()
                  .path(movieImageDTO.getPath())
                  .imgName(movieImageDTO.getImgName())
                  .uuid(movieImageDTO.getUuid())
                  .movie(movie)
                  .build();
              return movieImage;
            }
          }
      ).collect(Collectors.toList());
      entityMap.put("movieImageList",movieImageList);
    }
    return entityMap;
  }
  default MovieDTO entityToDto(Movie movie, List<MovieImage> movieImageList,
                               Double avg , int reviewCnt){
  MovieDTO movieDTO = MovieDTO.builder()
      .mno(movie.getMno())
      .title(movie.getTitle())
      .regDate(movie.getRegDate())
      .modDate(movie.getModDate())
      .build();
  List<MovieImageDTO> movieImageDTOList = movieImageList.stream().map(
      new Function<MovieImage, MovieImageDTO>() {
        @Override
        public MovieImageDTO apply(MovieImage movieImage) {
          MovieImageDTO movieImageDTO = MovieImageDTO.builder()
              .imgName(movieImage.getImgName())
              .path(movieImage.getPath())
              .uuid(movieImage.getUuid())
              .build();
          return movieImageDTO;
        }
      }
  ).collect(Collectors.toList());
  movieDTO.setAvg(avg);
  movieDTO.setReviewCnt(reviewCnt);
  return movieDTO;
  };
}

파일사이즈 예외처리하기

<script th:inline="javascript">
      function checkExtension(fileName, fileSize){
        maxSize = 1024*1024*10
        if(fileSize >= maxSize)
        {
          alert("파일 사이즈가 초과");
          return false;
        }
        // https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_expressions
        //const regex = new RegExp("(.*?)\.(exe|sh|zip|alz|tiff)$");
        const regex = new RegExp("(.*?)\.(jpg|jpeg|png|gif|bmp|pdf)$",'i');
      }
</script>

 

728x90
반응형

'PROGRAMING📚 > Spring📑' 카테고리의 다른 글

Spring / Spring boot  (1) 2024.09.26
Spring[EX06.코드] - 데이터 , 이미지 등록(통합구현)  (0) 2024.09.25
CSRF - API 서버  (0) 2024.09.25
JSP(JavaServer Pages)  (1) 2024.09.25
Spring : 구글 로그인 세션 만들기  (1) 2024.09.25

댓글