1. 파일 다운로드 시 CORS 및 파일 깨짐 문제
문제 상황
- CORS 에러 발생: GCS의 signed URL을 통한 직접 다운로드 시도 시 CORS 에러 발생
- 파일 깨짐 현상: 다운로드된 파일이 열리지 않거나 데이터가 손상됨
기존 코드
const handleDownload = async (fileName) => {
try {
const response = await downloadFile(fileName);
const blob = await fetch(response.data.downloadUrl).then(r => r.blob());
// ... 파일 다운로드 로직
} catch (error) {
console.error('Download failed:', error);
}
};
시도한 해결 방법
-
GCS CORS 설정 추가
[
{
"origin": ["*"],
"method": ["GET"],
"responseHeader": ["Content-Type"],
"maxAgeSeconds": 3600
}
]
- 결과: CORS 문제는 해결되었으나 파일 깨짐 현상 지속
-
프론트엔드에서 mode: 'no-cors' 설정
await fetch(response.data.downloadUrl, { mode: 'no-cors' });
- 결과: CORS 문제는 해결되었으나 파일 접근 불가
최종 해결 방법
1. 서버를 프록시로 사용하는 방식
백엔드 컨트롤러 수정:
@GetMapping("/download/{fileName}")
public ResponseEntity<Resource> downloadObject(
@PathVariable String fileName,
@RequestHeader("X-User-Id") String employeeId) throws GCSException {
try {
FileInfo fileInfo = fileInfoRepository.findByStoredFileNameAndUploader_EmployeeId(
fileName, employeeId)
.orElseThrow(() -> new GCSException("File not found or no permission"));
Blob blob = storage.get(bucketName, fileName);
ByteArrayResource resource = new ByteArrayResource(blob.getContent());
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(fileInfo.getContentType()))
.contentLength(blob.getSize())
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + fileInfo.getOriginalFileName() + "\"")
.body(resource);
} catch (Exception e) {
throw new GCSException("Failed to download file", e);
}
}
프론트엔드 다운로드 로직 수정:
export const downloadFile = async (fileName) => {
try {
const response = await gcsApi.get(`/download/${fileName}`, {
responseType: 'blob'
});
const blob = new Blob([response.data], {
type: response.headers['content-type']
});
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', originalFileName);
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(url);
link.remove();
} catch (error) {
console.error('Download failed:', error);
throw error;
}
};
2. 파일 업로드 크기 제한 문제
문제 상황
MaxUploadSizeExceededException 발생: 파일 크기가 Spring Boot의 기본 업로드 크기 제한을 초과함
에러 메시지
org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded
시도한 해결 방법
-
FileValidator에서 maxFileSize 설정
@Value("${file.max-size:10485760}")
private long maxFileSize;
- 결과: Spring의 Multipart 처리 전에 에러 발생
-
application.yml에 파일 크기 제한 설정
file:
max-size: 52428800 # 50MB
- 결과: 애플리케이션 레벨 검증은 통과했지만 여전히 Multipart 에러 발생
최종 해결 방법
Spring Boot의 Multipart 설정 추가:
spring:
servlet:
multipart:
max-file-size: 50MB
max-request-size: 50MB
file:
max-size: 52428800 # 50MB
설정 항목 설명
max-file-size: 단일 파일의 최대 크기
max-request-size: 전체 multipart 요청의 최대 크기
file.max-size: 애플리케이션 레벨에서의 파일 크기 제한
결론
파일 다운로드 문제
- 해결 방법: 서버 프록시 방식을 사용하여 GCS와 클라이언트 간의 통신 문제 해결
- 효과:
- CORS 문제 해결
- 파일 무결성 보장
- 보안성 향상
파일 업로드 크기 제한 문제
- 해결 방법: Spring Boot의 multipart 설정 추가
- 효과:
- 멀티파트 요청 처리 단계에서 파일 크기 제한 적용
- 애플리케이션 레벨의 파일 크기 검증
- 일관된 제한 설정으로 안정성 확보
1. 파일 다운로드 시 CORS 및 파일 깨짐 문제
문제 상황
기존 코드
시도한 해결 방법
GCS CORS 설정 추가
[ { "origin": ["*"], "method": ["GET"], "responseHeader": ["Content-Type"], "maxAgeSeconds": 3600 } ]프론트엔드에서
mode: 'no-cors'설정최종 해결 방법
1. 서버를 프록시로 사용하는 방식
백엔드 컨트롤러 수정:
프론트엔드 다운로드 로직 수정:
2. 파일 업로드 크기 제한 문제
문제 상황
MaxUploadSizeExceededException발생: 파일 크기가 Spring Boot의 기본 업로드 크기 제한을 초과함에러 메시지
시도한 해결 방법
FileValidator에서
maxFileSize설정application.yml에 파일 크기 제한 설정최종 해결 방법
Spring Boot의 Multipart 설정 추가:
설정 항목 설명
max-file-size: 단일 파일의 최대 크기max-request-size: 전체 multipart 요청의 최대 크기file.max-size: 애플리케이션 레벨에서의 파일 크기 제한결론
파일 다운로드 문제
파일 업로드 크기 제한 문제