[Java] 한글로 된 파일 업로드/다운로드 시 파일명 깨짐

파일 다운로드 Controller 설명

다음은 파일 다운로드를 처리하는 DownloadController의 구현 코드입니다. 이 컨트롤러는 파일 ID를 입력받아 해당 파일을 서버에서 다운로드할 수 있도록 응답을 생성합니다.

주요 코드 설명

1. 파일 조회 및 경로 생성

FileInfo fileInfo = fileService.selectFileInfo(fileId);

if(fileInfo == null){
    return ResponseEntity.notFound().build();
}

Path path = Paths.get(fileInfo.getFilePath(), fileInfo.getStoredFilename());
Resource resource = new UrlResource(path.toUri());

if(!resource.exists()){
    return ResponseEntity.notFound().build();
}
  • fileService를 이용해 데이터베이스에서 파일 정보를 조회합니다.
  • 파일 정보가 없으면 404 Not Found 응답을 반환합니다.
  • 파일의 저장 경로와 파일명을 이용해 파일의 절대 경로를 생성합니다.
  • 해당 경로를 UrlResource 객체로 변환하여 파일 자원으로 사용합니다.
  • 파일이 존재하지 않을 경우 404 Not Found를 반환합니다.

2. 파일명 UTF-8 인코딩

String encodedFileName = URLEncoder.encode(fileInfo.getOriginalFilename(), StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
String contentDisposition = "attachment; filename*=UTF-8''" + encodedFileName;
  • 파일명을 UTF-8로 인코딩합니다.
  • URLEncoder.encode 메서드는 공백을 +로 인코딩하므로, 이를 %20으로 변환하여 URL 표준에 맞게 수정합니다.
  • 인코딩된 파일명을 Content-Disposition 헤더에 추가하여 클라이언트에게 파일명을 명확히 전달합니다.
  • filename*=UTF-8'' 형식을 사용하여 UTF-8로 인코딩된 파일명임을 명시합니다.

3. ResponseEntity로 응답 생성

return ResponseEntity.ok()
    .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
    .body(resource);
  • HTTP 응답의 헤더에 Content-Disposition을 추가하여 파일이 첨부 파일임을 명시합니다.
  • 파일 내용을 body에 담아 클라이언트가 다운로드할 수 있도록 합니다.

코드 전체 흐름

@RequestMapping("/Download")
public class DownloadController {

    private static String UPLOAD_FOLDER = "D:/logs/";

    @Autowired
    FileService fileService;

    @GetMapping("/{fileId}")
    public ResponseEntity<Resource> downloadFile(@PathVariable("fileId") int fileId) throws MalformedURLException, UnsupportedEncodingException {

        FileInfo fileInfo = fileService.selectFileInfo(fileId);

        if(fileInfo == null){
            return ResponseEntity.notFound().build();
        }

        Path path = Paths.get(fileInfo.getFilePath(), fileInfo.getStoredFilename());
        Resource resource = new UrlResource(path.toUri());

        if(!resource.exists()){
            return ResponseEntity.notFound().build();
        }

        String encodedFileName = URLEncoder.encode(fileInfo.getOriginalFilename(), StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
        String contentDisposition = "attachment; filename*=UTF-8''" + encodedFileName;

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
                .body(resource);
    }
}

주요 포인트

  • UTF-8 인코딩: 한글 파일명 등 특수 문자가 포함된 파일명을 정확히 전달하기 위해 사용합니다.
  • replaceAll("\\+", "%20"): 공백 문자를 표준 URL 형식에 맞게 변환합니다.
  • Content-Disposition: 파일 다운로드 시 브라우저가 파일명을 올바르게 인식하도록 설정합니다.

Leave a Comment