Skip to content

πŸ“‚ μ²¨λΆ€νŒŒμΌ λ‹€μš΄λ‘œλ“œ μ‹œ ClassCastException 문제 ν•΄κ²°Β #85

@Tae4an

Description

@Tae4an

🐞 문제 상황

κ²Œμ‹œκΈ€μ— μ²¨λΆ€λœ 파일 λ‹€μš΄λ‘œλ“œ μ‹œ λ‹€μŒκ³Ό 같은 였λ₯˜κ°€ λ°œμƒ:

ClassCastException: org.springframework.core.io.UrlResource cannot be cast to com.office.app.dto.PostAttachmentDownloadDTO

πŸ“ λ°œμƒ μœ„μΉ˜:

  • Endpoint: GET /api/posts/{postId}/attachments/{fileId}/download
  • 상황: κ²Œμ‹œκΈ€μ— μ²¨λΆ€λœ 파일 λ‹€μš΄λ‘œλ“œ μ‹œλ„ 쀑 였λ₯˜ λ°œμƒ

πŸ” 원인 뢄석

1️⃣ Service κ³„μΈ΅μ—μ„œ Resource νƒ€μž…μ„ 직접 λ°˜ν™˜ν•˜λ €λ‹€ νƒ€μž… μΊμŠ€νŒ… 문제 λ°œμƒ
2️⃣ 파일 메타데이터(Content-Type, 파일λͺ… λ“±) λˆ„λ½
3️⃣ Controller와 Service κ°„ λ°˜ν™˜ νƒ€μž… 뢈일치


βœ… ν•΄κ²° 방법

πŸ—οΈ 1. PostAttachmentDownloadDTO 생성
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PostAttachmentDownloadDTO {
    private Resource resource;
    private String contentType;
    private String originalFileName;
}
πŸ› οΈ 2. Service λ©”μ„œλ“œ μˆ˜μ •
public PostAttachmentDownloadDTO downloadAttachment(Long postId, Long fileId, String employeeId) {
    PostAttachment attachment = postAttachmentRepository.findByIdAndPostId(fileId, postId)
        .orElseThrow(() -> new FileNotFoundException("νŒŒμΌμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."));

    GCSResponse gcsResponse = gcsService.downloadObject(attachment.getStoredFileName(), employeeId);

    return PostAttachmentDownloadDTO.builder()
        .resource(new UrlResource(new URL(gcsResponse.getDownloadUrl())))
        .contentType(attachment.getContentType())
        .originalFileName(attachment.getOriginalFileName())
        .build();
}
🌐 3. Controller 응닡 처리 κ°œμ„ 
@GetMapping("/{postId}/attachments/{fileId}/download")
public ResponseEntity<Resource> downloadAttachment(
        @PathVariable Long postId,
        @PathVariable Long fileId,
        Authentication authentication) {
    PostAttachmentDownloadDTO downloadInfo = 
        postAttachmentService.downloadAttachment(postId, fileId, authentication.getName());

    return ResponseEntity.ok()
        .contentType(MediaType.parseMediaType(downloadInfo.getContentType()))
        .header(HttpHeaders.CONTENT_DISPOSITION, 
            "attachment; filename=\"" + URLEncoder.encode(downloadInfo.getOriginalFileName(), StandardCharsets.UTF_8) + "\"")
        .body(downloadInfo.getResource());
}

✨ μ£Όμš” κ°œμ„ μ‚¬ν•­

  • 🎯 DTOλ₯Ό μ‚¬μš©ν•΄ 데이터 μΊ‘μŠν™”
  • πŸ“ Content-Type 및 Content-Disposition 헀더 μ„€μ •
  • 🌏 ν•œκΈ€ 파일λͺ… 처리λ₯Ό μœ„ν•œ URLEncoder 적용
  • πŸ”„ Service-Controller κ°„ μ±…μž„ 뢄리

πŸ’‘ κ²°κ³Ό

  • βœ… 파일 λ‹€μš΄λ‘œλ“œ κΈ°λŠ₯ 정상 μž‘λ™
  • βœ… ν•œκΈ€ 파일λͺ… 정상 처리
  • βœ… λΈŒλΌμš°μ € λ‹€μš΄λ‘œλ“œ λ™μž‘ 문제 ν•΄κ²°

πŸ“Œ μΆ”κ°€ 고렀사항

πŸ”’ λ³΄μ•ˆ κ°•ν™”: 파일 μ ‘κ·Ό κΆŒν•œ 검증
πŸ“ˆ λŒ€μš©λŸ‰ 파일 처리: 슀트리밍 방식 κ³ λ €


Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions