티스토리 뷰

728x90

하나의 form에서 여러 개의 file을 업로드하고 싶었다.

단순히 input 태그에 multiple을 붙이는게 아닌 파일 업로드가 가능한 필드가 여러개 있는 경우를 말하는 것이다.

 

정보가 너무 없어서 꽤나 고생했다. 

 

 

HTML에서 업로드부터 시작.

form 태그에 enctype="multipart/form-data" 작성

<form class="needs-validation" novalidate method="post" th:action="@{/seller/write}"
      th:object="${writeItemRequest}" enctype="multipart/form-data">

 

input 태그에 파일 업로드할 곳 작성.

name을 신경써서 작성

<div class="mb-3">
    <input class="form-control" type="file" name="mainImage" accept="image/png, image/jpeg"
           id="mainImage" aria-describedby="imageHelp">
</div>
<div class="mb-3">
    <input class="form-control" type="file" name="descriptionImage" accept="image/png, image/jpeg"
           id="descriptionImage" aria-describedby="descriptionImageHelp" multiple>
</div>

 

Controller에서 RequestParam으로 받기

 

@PostMapping("/write")
public String adminWriteAction(@Valid WriteItemRequest writeItemRequest,
                               @RequestParam("mainImage") MultipartFile file,
                               @RequestParam(value = "descriptionImage", required = false) List<MultipartFile> files,
                               @CurrentUser User user) {
                               
    sellerService.writeItem(writeItemRequest, file, files, user);
    return "redirect:/";
}

 

본인이 가장 고생했던 부분이 이쪽인데 

대표이미지 하나를 작성하는건 필수이고 나머지 설명에 관련된 이미지를 선택으로 두고싶었다.

그런데 논리적으로 맞게 해도 계속 IndexOutOfBounds 에러가 발생하는 것이었다.

 

직접 프린트 찍어가며 확인해본 결과 

List<MultipartFile> files로 들어오는 값이 null이나 empty가 아니라 ""이었다.

List가 비어있지도 않고 값이 있는 것도 아니라 계속 에러가 발생하는 것이 원인이었다.

그래서 List의 size도 1이었고 그 값이 처리도 되지 않아서 에러가 발생한 것.

 

평소 감각대로 List를 다뤘는데 평소에 거의 다루지 않았던 File의 I/O였던 것이 문제였다.

 

마지막으로 대표이미지 flag를 세우고 저장 후 마무리.

public Long writeItem(WriteItemRequest writeItemRequest, final MultipartFile file, final List<MultipartFile> files, final User user) {
    User userForId = userRepository.findById(user.getId())
                    .orElseThrow(() -> new UserNotFoundException("유저가 없습니다"));
    Seller seller = sellerRepository.findByUserIdAndIsActivatedTrue(userForId.getId())
                    .orElseThrow(() -> new SellerNotFoundException("판매자 자격이 없습니다"));

    List<Image> imageList = new ArrayList<>();

    Image mainImage = fileHandler.parseFilesInfo(file);
    mainImage.setIsMainImage(true);
    imageList.add(mainImage);

    if (!files.get(0).isEmpty()) {
        for (MultipartFile multipartFile : files) {
            imageList.add(fileHandler.parseFilesInfo(multipartFile));
        }
    }
    Item item = Item.builder()
            .name(writeItemRequest.getName())
            .description(writeItemRequest.getDescription())
            .price(writeItemRequest.getPrice())
            .stock(writeItemRequest.getStock())
            .seller(seller)
            .build();

    for (Image image : imageList) {
        item.addImage(imageRepository.save(image));
    }
    return itemRepository.save(item).getId();
}

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함