Backend/SpringBoot

클라이언트의 파일을 받아 처리하기

Dean83 2025. 9. 15. 14:12

파일을 클라이언트로 부터 받아 처리 하는 경우를 정리한다. 프레임워크가 잘되어 있어서 자동화가 잘 되어 있다. 

일단 고려해야 할 사항을 적어보면, 

 

  • 파일명은 그대로 쓰지 말고 변경해서 수정 
    • UUID 나 UUID + time 정보로 변경
  • 확장자를 확인할 것
    • 필요한 확장자 파일만 받아야 함. 
    • 확장자만 변경하여 서버를 공격할 스크립트를 심어 넣을 수도 있으므로 주의해야 함. 
      • 그럴리는 없겠지만, 서버와 같은 pc 내에 파일을 저장할경우. 보통은 클라우드에 저장한다. 
      • Tika 라이브러리 사용하여 실제 파일의 타입을 알아내는 것이 좋다.

 

1. yaml 파일 설정

spring:
  servlet:
    multipart:
      enabled : true 
      max-file-size: 10MB
      max-request-size: 20MB
      location : /위치
      file-size-threshold : 1MB
  • location 은 만일, 로컬에 저장할 경우 사용되는 외부 경로
  • file-size-threshold 는 작은용량의 파일은 메모리에 들고 있도록 할 수 있다.

 

2. Controller 예시

...
@RestController
@RequestMapping("/api/files")
public class FileController {

    @PostMapping("/upload-multiple")
    public String uploadMultipleFiles(@RequestParam("files") List<MultipartFile> files, @RequestParam("username") String username) throws IOException {
        try
        {
        	for (MultipartFile file : files) {
            ....파일명 변경, 확장자 확인등 작업 필요
			
            //로컬에 저장하는 경우
            File destFile = new File(filePath + "/" + savedName);
            
            //실제 클라이언트로 부터 받은 파일을 저장하는 부분
            file.transferTo(destFile);
            }

            return "Success";
        }
        catch(Exception e)
        {
        	... 로깅 등
            return "failed";
        }
    }
}
  • Tika 라이브러리 예
    • gradle 추가
implementation 'org.apache.tika:tika-core
implementation 'org.apache.tika:tika-parsers-standard-package

 

  • 사용 예시
@Service
public class ValidateFile
{
	private final Tika tika = new Tika();
    public boolean isCorrectFile(MultipartFile file)
    {
    	...
    	String type = tika.detect(file,getInputStream());
        ...
    }

}

 

3. S3에 업로드 예

  • gradle 추가 및 env에 추가한 키 값 설정등은 패스한다. 
....

@Service
public class S3Service {

    private final S3Client s3Client;

    @Value("${cloud.aws.s3.bucket}")
    private String bucketName;

    public S3Service(
            @Value("${cloud.aws.region}") String region,
            @Value("${cloud.aws.credentials.access-key}") String accessKey,
            @Value("${cloud.aws.credentials.secret-key}") String secretKey) {

        this.s3Client = S3Client.builder()
                .region(Region.of(region))
                .credentialsProvider(
                        StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))
                )
                .build();
    }

    public String uploadFile(MultipartFile file) throws Exception {
        String key = UUID.randomUUID() + "_" + file.getOriginalFilename();

        try (InputStream inputStream = file.getInputStream()) {
            PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .contentType(file.getContentType())
                    .build();

            s3Client.putObject(putObjectRequest,
                    software.amazon.awssdk.core.sync.RequestBody.fromInputStream(inputStream, file.getSize()));
        }

        return key; // 업로드된 파일의 S3 key 반환
    }
}