[api] FileController.java 컨벤션 맞춰 변경
This commit is contained in:
@@ -44,7 +44,7 @@ public class OpenApiConfig {
|
|||||||
.pathsToExclude(
|
.pathsToExclude(
|
||||||
"/admin/**"
|
"/admin/**"
|
||||||
, "/cors/**"
|
, "/cors/**"
|
||||||
, "/files/**"
|
, "/file/**"
|
||||||
, "/tusFiles/**"
|
, "/tusFiles/**"
|
||||||
, "/error"
|
, "/error"
|
||||||
, "/actuator/**"
|
, "/actuator/**"
|
||||||
@@ -66,7 +66,7 @@ public class OpenApiConfig {
|
|||||||
.group("900. common")
|
.group("900. common")
|
||||||
.pathsToMatch(
|
.pathsToMatch(
|
||||||
"/cors/**"
|
"/cors/**"
|
||||||
, "/files/**"
|
, "/file/**"
|
||||||
, "/tusFiles/**"
|
, "/tusFiles/**"
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public class SecurityConfig {
|
|||||||
, "/user/migrationUserList"
|
, "/user/migrationUserList"
|
||||||
, "/tusFiles/tusHook"
|
, "/tusFiles/tusHook"
|
||||||
, "/tusFiles/uploadAuth"
|
, "/tusFiles/uploadAuth"
|
||||||
, "/files/**"
|
, "/file/**"
|
||||||
).permitAll()
|
).permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
try {
|
try {
|
||||||
String requestUri = request.getRequestURI();
|
String requestUri = request.getRequestURI();
|
||||||
boolean adminRequest = requestUri.startsWith("/admin/");
|
boolean adminRequest = requestUri.startsWith("/admin/");
|
||||||
boolean sharedRequest = requestUri.startsWith("/tusFiles/") || requestUri.startsWith("/files/") || requestUri.startsWith("/cors/");
|
boolean sharedRequest = requestUri.startsWith("/tusFiles/") || requestUri.startsWith("/file/") || requestUri.startsWith("/cors/");
|
||||||
String token = resolveToken(request, adminRequest, sharedRequest);
|
String token = resolveToken(request, adminRequest, sharedRequest);
|
||||||
|
|
||||||
if (token != null && jwtTokenProvider.validateToken(token)) {
|
if (token != null && jwtTokenProvider.validateToken(token)) {
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Tag(
|
@Tag(
|
||||||
name = "902. 파일 업로드",
|
name = "902. 파일 업로드"
|
||||||
description = "DB 기록 없이 파일을 저장하고 uploadPath를 반환하는 단순 업로드 API입니다. SunEditor 이미지는 file-domain URL을 반환합니다."
|
, description = "DB 기록 없이 파일을 저장하고 uploadPath를 반환하는 단순 업로드 API입니다. SunEditor 이미지는 file-domain URL을 반환합니다."
|
||||||
)
|
)
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/files")
|
@RequestMapping("/file")
|
||||||
public class FileController {
|
public class FileController {
|
||||||
private final FileService fileService;
|
private final FileService fileService;
|
||||||
|
|
||||||
@@ -30,75 +30,79 @@ public class FileController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "단순 파일 업로드",
|
summary = "단순 파일 업로드"
|
||||||
description = """
|
, description = """
|
||||||
DB에 기록하지 않고 파일만 저장합니다.
|
DB에 기록하지 않고 파일만 저장합니다.
|
||||||
반환된 uploadPath는 이후 각 업무 테이블에 저장해서 view/download 경로로 사용할 수 있습니다.
|
반환된 uploadPath는 이후 각 업무 테이블에 저장해서 view/download 경로로 사용할 수 있습니다.
|
||||||
folder 값은 저장 폴더 키이며, 설정된 타입이면 해당 정책을 사용하고 설정되지 않은 값이면 전역 정책만 적용합니다.
|
folder 값은 저장 폴더 키이며, 설정된 타입이면 해당 정책을 사용하고 설정되지 않은 값이면 전역 정책만 적용합니다.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@PostMapping("/upload")
|
@PostMapping("/upload")
|
||||||
public ResponseEntity<ApiResponse<FileUploadVo>> upload(
|
public ResponseEntity<ApiResponse<FileUploadVo>> fileUpload(
|
||||||
@RequestParam String folder,
|
@RequestParam String folder
|
||||||
@RequestPart MultipartFile file
|
, @RequestPart MultipartFile file
|
||||||
) {
|
) {
|
||||||
FileUploadVo result = fileService.upload(folder, file);
|
FileUploadVo fileUploadVo = fileService.saveFileUpload(folder, file);
|
||||||
return ApiResponse.entity(result, ApiResponseCode.CODE_200);
|
return ApiResponse.entity(fileUploadVo, ApiResponseCode.CODE_200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "SunEditor 이미지 업로드",
|
summary = "SunEditor 이미지 업로드"
|
||||||
description = """
|
, description = """
|
||||||
SunEditor 이미지 업로드 전용 API입니다.
|
SunEditor 이미지 업로드 전용 API입니다.
|
||||||
업로드 파일을 저장한 뒤 SunEditor가 요구하는 result 배열 형태로 응답합니다.
|
업로드 파일을 저장한 뒤 SunEditor가 요구하는 result 배열 형태로 응답합니다.
|
||||||
응답 URL은 file.upload.view.file-domain 값과 uploadPath를 조합한 공개 file-domain URL입니다.
|
응답 URL은 file.upload.view.file-domain 값과 uploadPath를 조합한 공개 file-domain URL입니다.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@PostMapping("/suneditor/upload")
|
@PostMapping("/suneditor/upload")
|
||||||
public ResponseEntity<SunEditorUploadVo> sunEditorUpload(
|
public ResponseEntity<SunEditorUploadVo> fileSunEditorUpload(
|
||||||
@RequestParam(value = "folder", defaultValue = "editor") String folder,
|
@RequestParam(value = "folder", defaultValue = "editor") String folder
|
||||||
MultipartHttpServletRequest request
|
, MultipartHttpServletRequest request
|
||||||
) {
|
) {
|
||||||
List<SunEditorUploadVo.Item> result = new ArrayList<>();
|
List<SunEditorUploadVo.Item> sunEditorUploadItemList = new ArrayList<>();
|
||||||
|
|
||||||
for (MultipartFile file : request.getFileMap().values()) {
|
for (MultipartFile file : request.getFileMap().values()) {
|
||||||
FileUploadVo uploaded = fileService.upload(folder, file);
|
FileUploadVo uploaded = fileService.saveFileUpload(folder, file);
|
||||||
|
|
||||||
String imageUrl = fileService.buildImageUrl(uploaded.getUploadPath());
|
String imageUrl = fileService.buildImageUrl(uploaded.getUploadPath());
|
||||||
|
|
||||||
result.add(new SunEditorUploadVo.Item(
|
sunEditorUploadItemList.add(new SunEditorUploadVo.Item(
|
||||||
imageUrl,
|
imageUrl,
|
||||||
uploaded.getOriginalFileName(),
|
uploaded.getOriginalFileName(),
|
||||||
uploaded.getFileSize()
|
uploaded.getFileSize()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseEntity.ok(new SunEditorUploadVo(result));
|
return ResponseEntity.ok(new SunEditorUploadVo(sunEditorUploadItemList));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "파일 보기",
|
summary = "파일 보기"
|
||||||
description = """
|
, description = """
|
||||||
uploadPath 기준으로 파일을 inline 응답합니다.
|
uploadPath 기준으로 파일을 inline 응답합니다.
|
||||||
예: /uploads/notice/2026/05/08/sample.png
|
예: /uploads/notice/2026/05/08/sample.png
|
||||||
단순 업로드 결과의 uploadPath를 그대로 path 파라미터에 전달합니다.
|
단순 업로드 결과의 uploadPath를 그대로 path 파라미터에 전달합니다.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@GetMapping("/view")
|
@GetMapping("/view")
|
||||||
public ResponseEntity<Resource> view(@RequestParam String path) {
|
public ResponseEntity<Resource> fileView(
|
||||||
|
@RequestParam String path
|
||||||
|
) {
|
||||||
return fileService.resource(path, true);
|
return fileService.resource(path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "파일 다운로드",
|
summary = "파일 다운로드"
|
||||||
description = """
|
, description = """
|
||||||
uploadPath 기준으로 파일을 attachment 응답합니다.
|
uploadPath 기준으로 파일을 attachment 응답합니다.
|
||||||
예: /uploads/notice/2026/05/08/sample.pdf
|
예: /uploads/notice/2026/05/08/sample.pdf
|
||||||
단순 업로드 결과의 uploadPath를 그대로 path 파라미터에 전달합니다.
|
단순 업로드 결과의 uploadPath를 그대로 path 파라미터에 전달합니다.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@GetMapping("/download")
|
@GetMapping("/download")
|
||||||
public ResponseEntity<Resource> download(@RequestParam String path) {
|
public ResponseEntity<Resource> fileDownload(
|
||||||
|
@RequestParam String path
|
||||||
|
) {
|
||||||
return fileService.resource(path, false);
|
return fileService.resource(path, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,18 @@ import com.alist.api.modules.file.properties.FileUploadProperties;
|
|||||||
import com.alist.api.modules.file.vo.FileUploadVo;
|
import com.alist.api.modules.file.vo.FileUploadVo;
|
||||||
import org.springframework.core.io.InputStreamResource;
|
import org.springframework.core.io.InputStreamResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.*;
|
import org.springframework.http.ContentDisposition;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.*;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -28,7 +32,7 @@ public class FileService {
|
|||||||
this.fileUploadImageService = fileUploadImageService;
|
this.fileUploadImageService = fileUploadImageService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileUploadVo upload(String folder, MultipartFile file) {
|
public FileUploadVo saveFileUpload(String folder, MultipartFile file) {
|
||||||
if (folder == null || folder.isBlank()) throw new IllegalArgumentException("invalid folder");
|
if (folder == null || folder.isBlank()) throw new IllegalArgumentException("invalid folder");
|
||||||
if (file == null || file.isEmpty()) throw new IllegalArgumentException("empty file");
|
if (file == null || file.isEmpty()) throw new IllegalArgumentException("empty file");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user