스프링 파일 업로드 #1. 비동기 처리 (2)

Chan Young Jeong·2023년 4월 28일
0

스프링

목록 보기
6/7

이전 포스팅에는 파일을 동기적으로 업로드하는 방식에 대해 알아보았는데 이어서 비동기적으로 파일을 업로드 해보겠습니다.

프로젝트를 진행하면서 파일을 업로드할 때 사용자가 서버에 파일이 끝까지 저장될 때까지 계속해서 응답을 기다리게 되는 문제가 발생했습니다.

진행한 프로젝트에서는 단순히 파일을 업로드하고 끝나는게 아니라 영상에 필터를 입히고 다양한 처리를 해줘야하기 때문에 시간이 꽤 걸리는 작업이었습니다. 이렇게 되면 사용성이 떨어지기 때문에 이를 개선하고자 비동기적으로 먼저 응답을 보내는 방식으로 코드를 작성했습니다.

스프링에서 비동기 메서드를 작성하는 방법은 참고

👍 컨트롤러

BasicController

@RestController
@RequiredArgsConstructor
public class BasicController{

  private final BasicService service;
  
  @Value("${file.dir}")
  private String fileDir;

  @PostMapping("/upload")
  public ResponseEntity<String> saveFile(@RequestParam String itemName, @RequestParam MultipartFile file) {

      if (!file.isEmpty()) {
          String fullPath = fileDir + file.getOriginalFilename()
          
          log.info("-------BasicController 비동기 처리 메소드 실행-------");
          service.processFile(file,fullPath);
          log.info("-------BasicController 비동기 처리 메서드 종료-------");
      }

  return new ResponseEntity<>(fullPath, HttpStatus.CREATED);
  }
}

😘 서비스

BasicService

@Service
@Async
public class BasicService {
    public void processFile(MultipartFile file,String fullPath) {

        if (!file.isEmpty()) {
        	log.info("-------BasicService 비동기 처리 실행 -------");			
            
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

			try {
                file.transferTo(new File(fullPath));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            log.info("-------BasicService 비동기 처리 종료 -------");
        }
        
    }
}

😒 FileNotFoundException


java.lang.RuntimeException: java.io.IOException: java.io.FileNotFoundException: C:\Users\AppData\Local\Temp\tomcat.8080.3037933434984946\work\Tomcat\localhost\ROOT\upload_a81d4bd7_c23a_43ba_9016_43e59017d84a_00000001.tmp (지정된 파일을 찾을 수 없습니다)

분명 비동기적으로 잘 처리된 거 같은데 다음과 같은 에러가 발생.. 그 이유는?

BasicController에서 BasicServiceMulitpartFile 객체인 file을 전달하는데 이때 응답이 먼저 비동기적으로 보내지면 file 객체는 메모리에서 deallocate되버린다. 참고 따라서 BasicService에서 전달 받은 file객체를 처리하려고 하면 FileNotFoundException 발생하는 것! 해결 방법은 BasicService로 전달하기 전 메모리에 저장하기..!

BasicController

@RestController
@RequiredArgsConstructor
public class BasicController{

  private final BasicService service;
  
  @Value("${file.dir}")
  private String fileDir;

  @PostMapping("/upload")
  public ResponseEntity<String> saveFile(@RequestParam String itemName, @RequestParam MultipartFile file) {

      if (!file.isEmpty()) {
          String fullPath = fileDir + file.getOriginalFilename()
          
          log.info("-------BasicController 비동기 처리 메소드 실행-------");
          service.processFile(file.getBytes(),fullPath);
          log.info("-------BasicController 비동기 처리 메서드 종료-------");
      }

  return new ResponseEntity<>(fullPath, HttpStatus.CREATED);
  }
}

BasicService

public void processFile(byte[] file,String fullPath) {
		...
}

더 나아가기

  • 만약에 동영상을 보내고 응답을 보냈는데 파일 처리중에 에러가 발생하면 클라이언트에게 어떻게 알려주지?

  • 애초에 큰 파일을 클라이언트에서 서버로 전송하는데 시간이 오래걸린다.


https://stackoverflow.com/questions/36565597/spring-async-file-upload-and-processing/36690261#36690261

0개의 댓글