카테고리 없음

파일 업로드 NoSuchFileException

dev_ajrqkq 2024. 10. 13. 02:13

https://girokeulhaja.tistory.com/55

 

CompletableFuture 비동기 처리로 응답 속도 향상 시키기

기존 코드 Controller@PostMappingpublic ResponseEntity uploadImage(@RequestParam("file") MultipartFile file) { try { // 1. DB에 파일 메타데이터 저장 및 응답 ImageResponse imageResponse = uploadService.saveImageMetadata(file); // 2. 비동

girokeulhaja.tistory.com

 

위 코드를 제대로 테스트 안 하고 응답 속도 개선만 확인했더니 대참사가 일어났다 ㅎㅎ

baboㅠ

 

바로 NoSuchFileException 에러가 계속 뜨는 거..

간헐적으로 나는 에러인줄 알았는데

 

InputStream은 한 번 읽으면 그 상태가 변경되어 더 이상 사용할 수 없게 되어 생기는 오류인듯,,

 

1. 이미지 크기 확일할 때 한 번

BufferedImage bufferedImage = ImageIO.read(file.getInputStream());

 

2. minio에 저장할 때 한 번

.stream(file.getInputStream(), file.getSize(), -1)

 

보통 2번 코드에서 오류가 잡히길래 뭔가했더니,,

파일을 두번째 읽을 때는 MultipartFile의 InputStream이 이미 소비되어 문제가 발생한다고 한다.

 

file.getInputStream() 또는 file.getBytes()를 호출하면, MultipartFile의 내용을 읽게 된다.

이 시점에서 InputStream이 소비되므로 이후에 다시 file을 읽으려고 하면 NoSuchFileException이 발생한다.

 

public CompletableFuture<String> saveImageMetadata(MultipartFile file) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                // 파일 데이터를 메모리에 저장
                byte[] fileBytes = file.getBytes();

                // 파일 데이터를 기반으로 InputStream 생성
                ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileBytes);

                // 업로드 파일명을 불러옴
                String originalName = file.getOriginalFilename();

                // 파일 이름이 존재하지 않는 경우
                if (originalName == null) throw new IllegalArgumentException("잘못된 파일입니다.");

                // 파일 정보 분리
                String[] fileInfos = FileUtil.splitFileName(originalName);

                // 확장자 체크
                ImageExtension extension = ImageExtension.findByKey(fileInfos[1])
                        .orElseThrow(() -> new Exception("지원하지 않는 확장자 입니다."));

                // 이미지 크기 확인
                BufferedImage bufferedImage = ImageIO.read(byteArrayInputStream);
                int imageWidth = bufferedImage.getWidth();
                int imageHeight = bufferedImage.getHeight();

                ImageRequest imageRequest = ImageRequest.create(
                        originalName,
                        extension.getKey(),
                        cdnBaseUrl,
                        imageWidth,
                        imageHeight
                );

                // 메타데이터 저장
                ImageResponse imageResponse = dataService.uploadImage(imageRequest);

                // 새롭게 InputStream을 생성하여 minio에 이미지 업로드
                uploadImage(new ByteArrayInputStream(fileBytes), file.getContentType(), imageResponse);

                return imageResponse.getOriginalFileUUID().toString();
            } catch (Exception e) {
                log.error("이미지 메타데이터 저장 중 오류 발생: ", e);
                throw new RuntimeException(e);
            }
        });
    }