인프런 커뮤니티 질문&답변

jkshin님의 프로필 이미지

작성한 질문수

코드로 배우는 React with 스프링부트 API서버

서비스계층과 컨트롤러(3)-상품수정

서비스계층과컨트롤러(3) 상품수정

24.05.22 20:28 작성

·

240

0

@PutMapping("/{pno}")
public Map<String, String> modify(@PathVariable Long pno, ProductDTO productDTO) {

    // productDTO안에 pno값만 고정
    productDTO.setPno(pno);

    // 원래 상품을 가지고 온다. old product 가져온다. DB에 저장되어 있는 저장된 정보
    ProductDTO oldProductDTO = productService.get(pno);

    // 새로 업로드할 파일 가져온다.
    List<MultipartFile> files = productDTO.getFiles();

    // 새로 업로드할 파일 저장
    List<String> currentUploadFileNames = fileUtil.saveFiles(files);

    // 지워지지 않는 파일들 keep files 예전 파일 그대로 있는 것
    List<String> uploadedFileNames = productDTO.getUploadFileNames();

    if(currentUploadFileNames != null && !currentUploadFileNames.isEmpty()) {
        
        uploadedFileNames.addAll(currentUploadFileNames);
    }
    
    // 수정하기
    productService.modify(productDTO);
    
    // 오래된 파일이 문제. 지워져야 하는 파일들 처리
    // 기존 파일들을 가져온다.
    List<String> oldFileNames = oldProductDTO.getUploadFileNames();

    if(oldFileNames != null && !oldFileNames.isEmpty()) {

        // 기존 파일 남아 있는지 확인
        // uploadedFileNames에서 없다는건 이 파일은 이제 존재할 의미가 없다는것 그런것만 골라서 모은다.
        List<String> removeFiles =
            oldFileNames.stream().filter(fileName -> uploadedFileNames.indexOf(fileName) == -1 )
                .collect(Collectors.toList());

        // 삭제한다.
        fileUtil.deleteFiles(removeFiles);
    }

    return Map.of("RESULT", "SUCCESS");
}

ProductController 에 이 메서드를 입력하고

ProductService에는

// 수정
void modify(ProductDTO productDTO);

이걸 입력하고

ProductServiceImpl에는

@Override
public void modify(ProductDTO productDTO) {

    // 조회
    Optional<Product> result = productRepository.findById(productDTO.getPno());

    Product product = result.orElseThrow();

    // 변경내용 반영
    product.changePrice(productDTO.getPrice());
    product.changeName(productDTO.getPname());
    product.changeDesc(productDTO.getPdesc());
    product.changeDel(productDTO.isDelFlag());

    // 이미지 처리를 위해 목록을 비운다.
    List<String> uploadFileNames = productDTO.getUploadFileNames();

    product.clearList();

    if(uploadFileNames != null && uploadFileNames.isEmpty()) {

        uploadFileNames.forEach(uploadName ->{
            product.addImageString(uploadName);
        });

    }

    // 저장될 때 파일이 문제 파일이 변경됐는지 알 수 가 없다.
    productRepository.save(product);

}


private ProductDTO entityToDTO(Product product) {


    ProductDTO productDTO = ProductDTO.builder()
            .pno(product.getPno())
            .pname(product.getPname())
            .pdesc(product.getPdesc())
            .price(product.getPrice())
            .delFlag(product.isDelFlag())
            .build();

    
    List<ProductImage> imageList = product.getImageList();

    if(imageList == null || imageList.isEmpty()) {
        return productDTO;
    }
    
    // 상품 이미지 목록 문자열로 바꾸기
    List<String> fileNameList = imageList.stream().map(productImage ->
            productImage.getFileName()).toList();

    productDTO.setUploadFileNames(fileNameList);

    return productDTO;
}

 

이걸 입력하고 postman에서 PUT방식으로 해서 기존 이미지파일 내용을 그대로 복사해서 테스트를 하는데

"msg": "Validation failed for argument [1] in public java.util.Map<java.lang.String, java.lang.String> org.zerock.apiserver.controller.ProductController.modify(java.lang.Long,org.zerock.apiserver.dto.ProductDTO): [Field error in object 'productDTO' on field 'uploadFileNames': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@192a0968]; codes [typeMismatch.productDTO.uploadFileNames,typeMismatch.uploadFileNames,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [productDTO.uploadFileNames,uploadFileNames]; arguments []; default message [uploadFileNames]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.util.List' for property 'uploadFileNames'; Cannot convert value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.lang.String' for property 'uploadFileNames[0]': no matching editors or conversion strategy found]] "

이런 에러가 계속 발생하는데요 왜 그럴까요 ㅠ

postman에서 출력하는 메세지입니다.

 

GTP에 입력해서 물어봤는데

ProductControllermodify 메서드에서 ProductDTO 객체의 uploadFileNames 필드가 잘못된 타입으로 전달되었기 때문에 발생합니다.

 

이런 메세지를 주는데 강의 내용과 똑같이 입력했는데 왜 이런 메세지를 뱉어내는지 잘 모르겠습니다 ㅠ

답변 1

0

구멍가게코딩단님의 프로필 이미지
구멍가게코딩단
지식공유자

2024. 05. 22. 22:50

해당 강의의 22:17초 근처를 보시면 files라는 이름이 MultipartFile들인데요.. 에러 메시지를 보면

 

Cannot convert value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.lang.String' for property 'uploadFileNames[0]':

 

라고 나오고 있습니다.

 

uploadFileNames는 문자열로 기존에 업로드된 파일들 중에서 남겨두는 파일들이었으니 .. 문자열이 맞습니다.

 

Postman에서 files는 파일로, uploadFileNames는 문자열로 되었는지 확인해 보셔야 할 듯 하네요

jkshin님의 프로필 이미지
jkshin
질문자

2024. 05. 23. 10:59

감사합니다 원인을 찾아서 해결했습니다~!

jkshin님의 프로필 이미지

작성한 질문수

질문하기