[api] tus 수정
This commit is contained in:
@@ -6,6 +6,7 @@ import com.alist.api.common.utils.SecurityUtil;
|
|||||||
import com.alist.api.modules.tusFile.dto.*;
|
import com.alist.api.modules.tusFile.dto.*;
|
||||||
import com.alist.api.modules.tusFile.form.*;
|
import com.alist.api.modules.tusFile.form.*;
|
||||||
import com.alist.api.modules.tusFile.service.TusFileService;
|
import com.alist.api.modules.tusFile.service.TusFileService;
|
||||||
|
import com.alist.api.modules.tusFile.vo.*;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
@@ -43,29 +44,29 @@ public class TusFileController {
|
|||||||
, description = "업로드 대상 파일 정보를 DB에 등록하고 fileUuid/uploadToken을 발급합니다."
|
, description = "업로드 대상 파일 정보를 DB에 등록하고 fileUuid/uploadToken을 발급합니다."
|
||||||
)
|
)
|
||||||
@PostMapping("/upload/init")
|
@PostMapping("/upload/init")
|
||||||
public ResponseEntity<ApiResponse<FileUploadDto>> tusFileUploadInit(
|
public ResponseEntity<ApiResponse<TusFileUploadInitVo>> tusFileUploadInit(
|
||||||
@Valid @RequestBody FileUploadForm fileUploadForm
|
@Valid @RequestBody TusFileUploadInitForm tusFileUploadInitForm
|
||||||
) {
|
) {
|
||||||
FileUploadDto fileUploadDto = fileUploadForm.toFileUploadDto();
|
TusFileUploadInitDto tusFileUploadInitDto = tusFileUploadInitForm.toDto();
|
||||||
|
|
||||||
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
||||||
|
|
||||||
if (userTokenIdx == null) {
|
if (userTokenIdx == null) {
|
||||||
return ApiResponse.entity(new FileUploadDto(), ApiResponseCode.CODE_401);
|
return ApiResponse.entity(new TusFileUploadInitVo(), ApiResponseCode.CODE_401);
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer userIdx = tusFileService.selectUserIdxByUserTokenIdx(userTokenIdx);
|
Integer userIdx = tusFileService.selectUserIdxByUserTokenIdx(userTokenIdx);
|
||||||
|
|
||||||
if (userIdx == null) {
|
if (userIdx == null) {
|
||||||
return ApiResponse.entity(new FileUploadDto(), ApiResponseCode.CODE_401);
|
return ApiResponse.entity(new TusFileUploadInitVo(), ApiResponseCode.CODE_401);
|
||||||
}
|
}
|
||||||
|
|
||||||
fileUploadDto.setUserIdx(userIdx);
|
tusFileUploadInitDto.setUserIdx(userIdx);
|
||||||
fileUploadDto.setUserTokenIdx(userTokenIdx);
|
tusFileUploadInitDto.setUserTokenIdx(userTokenIdx);
|
||||||
|
|
||||||
FileUploadDto fileUploadResult = tusFileService.insertFileInit(fileUploadDto);
|
TusFileUploadInitVo tusFileUploadInitVo = tusFileService.insertTusFileUploadInit(tusFileUploadInitDto);
|
||||||
|
|
||||||
return ApiResponse.entity(fileUploadResult, ApiResponseCode.CODE_200);
|
return ApiResponse.entity(tusFileUploadInitVo, ApiResponseCode.CODE_200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
@@ -86,17 +87,17 @@ public class TusFileController {
|
|||||||
return ApiResponse.entity("", ApiResponseCode.CODE_403);
|
return ApiResponse.entity("", ApiResponseCode.CODE_403);
|
||||||
}
|
}
|
||||||
|
|
||||||
UploadTokenDto uploadTokenDto = new UploadTokenDto();
|
TusFileUploadAuthDto tusFileUploadAuthDto = new TusFileUploadAuthDto();
|
||||||
uploadTokenDto.setUploadToken(uploadToken.substring(7).trim());
|
tusFileUploadAuthDto.setUploadToken(uploadToken.substring(7).trim());
|
||||||
uploadTokenDto.setFileUuid(fileUuid.trim());
|
tusFileUploadAuthDto.setFileUuid(fileUuid.trim());
|
||||||
uploadTokenDto.setUploadMetadataRaw(uploadMetadata);
|
tusFileUploadAuthDto.setUploadMetadataRaw(uploadMetadata);
|
||||||
uploadTokenDto.setUploadLengthRaw(uploadLength);
|
tusFileUploadAuthDto.setUploadLengthRaw(uploadLength);
|
||||||
|
|
||||||
UploadTokenDto uploadTokenCheck = tusFileService.isUploadTokenCheck(uploadTokenDto);
|
TusFileUploadAuthVo tusFileUploadAuthVo = tusFileService.selectTusFileUploadAuth(tusFileUploadAuthDto);
|
||||||
|
|
||||||
if (uploadTokenCheck.getResultCode() == 401) {
|
if (tusFileUploadAuthVo.getResultCode() == 401) {
|
||||||
return ApiResponse.entity("", ApiResponseCode.CODE_401);
|
return ApiResponse.entity("", ApiResponseCode.CODE_401);
|
||||||
} else if (uploadTokenCheck.getResultCode() == 403) {
|
} else if (tusFileUploadAuthVo.getResultCode() == 403) {
|
||||||
return ApiResponse.entity("", ApiResponseCode.CODE_403);
|
return ApiResponse.entity("", ApiResponseCode.CODE_403);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,14 +109,16 @@ public class TusFileController {
|
|||||||
, description = "fileUuid 기준으로 Redis/DB 업로드 상태(진행률, 상태값)를 조회합니다."
|
, description = "fileUuid 기준으로 Redis/DB 업로드 상태(진행률, 상태값)를 조회합니다."
|
||||||
)
|
)
|
||||||
@PostMapping("/upload/status")
|
@PostMapping("/upload/status")
|
||||||
public ResponseEntity<ApiResponse<UploadStatusDto>> tusFileUploadStatus(
|
public ResponseEntity<ApiResponse<TusFileUploadStatusVo>> tusFileUploadStatus(
|
||||||
@Valid @RequestBody UploadStatusForm uploadStatusForm
|
@Valid @RequestBody TusFileUploadStatusForm tusFileUploadStatusForm
|
||||||
) {
|
) {
|
||||||
UploadStatusDto status = tusFileService.getUploadStatus(uploadStatusForm.toUploadStatusDto());
|
TusFileUploadStatusVo tusFileUploadStatusVo = tusFileService.loadTusFileUploadStatus(tusFileUploadStatusForm.toDto());
|
||||||
if (status == null) {
|
|
||||||
return ApiResponse.entity(new UploadStatusDto(), ApiResponseCode.CODE_2003);
|
if (tusFileUploadStatusVo == null) {
|
||||||
|
return ApiResponse.entity(new TusFileUploadStatusVo(), ApiResponseCode.CODE_2003);
|
||||||
}
|
}
|
||||||
return ApiResponse.entity(status, ApiResponseCode.CODE_200);
|
|
||||||
|
return ApiResponse.entity(tusFileUploadStatusVo, ApiResponseCode.CODE_200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
@@ -123,11 +126,13 @@ public class TusFileController {
|
|||||||
, description = "tusd에서 전달되는 pre-create/post-receive/post-finish/post-terminate 이벤트를 반영합니다."
|
, description = "tusd에서 전달되는 pre-create/post-receive/post-finish/post-terminate 이벤트를 반영합니다."
|
||||||
)
|
)
|
||||||
@PostMapping("/hook")
|
@PostMapping("/hook")
|
||||||
public ResponseEntity<ApiResponse<String>> tusFileHook(@RequestBody TusHookForm tusHookForm) {
|
public ResponseEntity<ApiResponse<String>> tusFileHook(@RequestBody TusFileHookForm tusFileHookForm) {
|
||||||
boolean accepted = tusFileService.updateFileUploadStatus(tusHookForm.toTusHookDto());
|
TusFileHookDto tusFileHookDto = tusFileHookForm.toDto();
|
||||||
|
|
||||||
|
boolean accepted = tusFileService.updateTusFileHook(tusFileHookDto);
|
||||||
|
|
||||||
if (accepted) {
|
if (accepted) {
|
||||||
tusFileService.saveUploadStatusRedisTusHook(tusHookForm.toTusHookDto());
|
tusFileService.saveTusFileHookStatusRedis(tusFileHookDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiResponse.entity("", ApiResponseCode.CODE_200);
|
return ApiResponse.entity("", ApiResponseCode.CODE_200);
|
||||||
@@ -139,7 +144,7 @@ public class TusFileController {
|
|||||||
)
|
)
|
||||||
@PostMapping("/upload/cancel")
|
@PostMapping("/upload/cancel")
|
||||||
public ResponseEntity<ApiResponse<String>> tusFileUploadCancel(
|
public ResponseEntity<ApiResponse<String>> tusFileUploadCancel(
|
||||||
@Valid @RequestBody UploadCancelForm uploadCancelForm
|
@Valid @RequestBody TusFileUploadCancelForm tusFileUploadCancelForm
|
||||||
) {
|
) {
|
||||||
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
||||||
|
|
||||||
@@ -147,14 +152,12 @@ public class TusFileController {
|
|||||||
return ApiResponse.entity("", ApiResponseCode.CODE_401);
|
return ApiResponse.entity("", ApiResponseCode.CODE_401);
|
||||||
}
|
}
|
||||||
|
|
||||||
UploadCancelDto uploadCancelDto = new UploadCancelDto();
|
TusFileUploadCancelDto tusFileUploadCancelDto = tusFileUploadCancelForm.toDto();
|
||||||
|
tusFileUploadCancelDto.setUserTokenIdx(userTokenIdx);
|
||||||
|
|
||||||
uploadCancelDto.setFileUuid(uploadCancelForm.getFileUuid().trim());
|
TusFileUploadCancelVo tusFileUploadCancelVo = tusFileService.updateTusFileUploadCancel(tusFileUploadCancelDto);
|
||||||
uploadCancelDto.setUserTokenIdx(userTokenIdx);
|
|
||||||
|
|
||||||
boolean canceled = tusFileService.updateUploadCancel(uploadCancelDto);
|
if (!tusFileUploadCancelVo.isCanceled()) {
|
||||||
|
|
||||||
if (!canceled) {
|
|
||||||
return ApiResponse.entity("", ApiResponseCode.CODE_2005, "업로드 취소");
|
return ApiResponse.entity("", ApiResponseCode.CODE_2005, "업로드 취소");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,62 +166,63 @@ public class TusFileController {
|
|||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "파일 목록 조회"
|
summary = "파일 목록 조회"
|
||||||
, description = "FILE_MASTER_IDX 기준으로 완료된 파일 목록을 조회합니다.")
|
, description = "FILE_MASTER_IDX 기준으로 완료된 파일 목록을 조회합니다."
|
||||||
|
)
|
||||||
@GetMapping("/list/{fileMasterIdx}")
|
@GetMapping("/list/{fileMasterIdx}")
|
||||||
public ResponseEntity<ApiResponse<FileDownloadListDto>> tusFileList(
|
public ResponseEntity<ApiResponse<TusFileListVo>> tusFileList(
|
||||||
@PathVariable Long fileMasterIdx
|
@PathVariable Long fileMasterIdx
|
||||||
) {
|
) {
|
||||||
|
TusFileListDto tusFileListDto = new TusFileListDto();
|
||||||
|
tusFileListDto.setFileMasterIdx(fileMasterIdx);
|
||||||
|
|
||||||
FileDownloadDto fileDownloadDto = new FileDownloadDto();
|
TusFileListVo tusFileListVo = tusFileService.selectTusFileList(tusFileListDto);
|
||||||
fileDownloadDto.setFileMasterIdx(fileMasterIdx);
|
|
||||||
|
|
||||||
FileDownloadListDto fileDownloadList = tusFileService.selectFileDownloadListByFileMasterIdx(fileDownloadDto);
|
if (tusFileListVo.getResultCode() == 401) {
|
||||||
|
return ApiResponse.entity(tusFileListVo, ApiResponseCode.CODE_401);
|
||||||
if (fileDownloadList.getResultCode() == 401) {
|
|
||||||
return ApiResponse.entity(fileDownloadList, ApiResponseCode.CODE_401);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiResponse.entity(fileDownloadList, ApiResponseCode.CODE_2001, "파일");
|
return ApiResponse.entity(tusFileListVo, ApiResponseCode.CODE_2001, "파일");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "파일 보기"
|
summary = "파일 보기"
|
||||||
, description = "권한 확인 후 Nginx X-Accel-Redirect로 파일을 inline 조회합니다.")
|
, description = "권한 확인 후 Nginx X-Accel-Redirect로 파일을 inline 조회합니다."
|
||||||
|
)
|
||||||
@GetMapping("/view/{fileUuid}")
|
@GetMapping("/view/{fileUuid}")
|
||||||
public ResponseEntity<Resource> tusFileView(
|
public ResponseEntity<Resource> tusFileView(
|
||||||
@PathVariable String fileUuid
|
@PathVariable String fileUuid
|
||||||
, HttpServletRequest request
|
, HttpServletRequest request
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
FileDownloadDto fileDownloadDto = new FileDownloadDto();
|
TusFileViewOrDownloadDto tusFileViewOrDownloadDto = new TusFileViewOrDownloadDto();
|
||||||
fileDownloadDto.setFileUuid(fileUuid);
|
tusFileViewOrDownloadDto.setFileUuid(fileUuid);
|
||||||
fileDownloadDto.setEventType("VIEW");
|
tusFileViewOrDownloadDto.setEventType("VIEW");
|
||||||
fileDownloadDto.setClientIp(request.getRemoteAddr());
|
tusFileViewOrDownloadDto.setClientIp(request.getRemoteAddr());
|
||||||
fileDownloadDto.setUserAgent(request.getHeader("User-Agent"));
|
tusFileViewOrDownloadDto.setUserAgent(request.getHeader("User-Agent"));
|
||||||
fileDownloadDto.setReferer(request.getHeader("Referer"));
|
tusFileViewOrDownloadDto.setReferer(request.getHeader("Referer"));
|
||||||
|
|
||||||
FileDownloadDto target = tusFileService.selectFileViewOrDownload(fileDownloadDto);
|
TusFileViewOrDownloadVo tusFileViewOrDownloadVo = tusFileService.selectTusFileViewOrDownload(tusFileViewOrDownloadDto);
|
||||||
|
|
||||||
if (target == null) {
|
if (tusFileViewOrDownloadVo == null) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
Path filePath = tusFileService.resolveStoredFilePath(target.getSavePath());
|
Path filePath = tusFileService.resolveStoredFilePath(tusFileViewOrDownloadVo.getSavePath());
|
||||||
|
|
||||||
if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) {
|
if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource resource = new InputStreamResource(Files.newInputStream(filePath));
|
Resource resource = new InputStreamResource(Files.newInputStream(filePath));
|
||||||
String contentType = target.getContentType() == null
|
String contentType = tusFileViewOrDownloadVo.getContentType() == null
|
||||||
? "application/octet-stream"
|
? "application/octet-stream"
|
||||||
: target.getContentType();
|
: tusFileViewOrDownloadVo.getContentType();
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.contentType(MediaType.parseMediaType(contentType))
|
.contentType(MediaType.parseMediaType(contentType))
|
||||||
.contentLength(Files.size(filePath))
|
.contentLength(Files.size(filePath))
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||||
ContentDisposition.inline()
|
ContentDisposition.inline()
|
||||||
.filename(target.getOriginName(), StandardCharsets.UTF_8)
|
.filename(tusFileViewOrDownloadVo.getOriginName(), StandardCharsets.UTF_8)
|
||||||
.build()
|
.build()
|
||||||
.toString())
|
.toString())
|
||||||
.body(resource);
|
.body(resource);
|
||||||
@@ -226,58 +230,59 @@ public class TusFileController {
|
|||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "파일 다운로드"
|
summary = "파일 다운로드"
|
||||||
, description = "권한 확인 후 파일 다운로드 로그를 남기고 redirect 또는 Nginx X-Accel-Redirect로 파일 다운로드 합니다.")
|
, description = "권한 확인 후 파일 다운로드 로그를 남기고 redirect 또는 Nginx X-Accel-Redirect로 파일 다운로드 합니다."
|
||||||
|
)
|
||||||
@GetMapping("/download/{fileUuid}")
|
@GetMapping("/download/{fileUuid}")
|
||||||
public ResponseEntity<Resource> tusFileDownload(
|
public ResponseEntity<Resource> tusFileDownload(
|
||||||
@PathVariable String fileUuid
|
@PathVariable String fileUuid
|
||||||
, HttpServletRequest request
|
, HttpServletRequest request
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
FileDownloadDto fileDownloadDto = new FileDownloadDto();
|
TusFileViewOrDownloadDto tusFileViewOrDownloadDto = new TusFileViewOrDownloadDto();
|
||||||
fileDownloadDto.setFileUuid(fileUuid);
|
tusFileViewOrDownloadDto.setFileUuid(fileUuid);
|
||||||
fileDownloadDto.setEventType("DOWNLOAD");
|
tusFileViewOrDownloadDto.setEventType("DOWNLOAD");
|
||||||
fileDownloadDto.setClientIp(request.getRemoteAddr());
|
tusFileViewOrDownloadDto.setClientIp(request.getRemoteAddr());
|
||||||
fileDownloadDto.setUserAgent(request.getHeader("User-Agent"));
|
tusFileViewOrDownloadDto.setUserAgent(request.getHeader("User-Agent"));
|
||||||
fileDownloadDto.setReferer(request.getHeader("Referer"));
|
tusFileViewOrDownloadDto.setReferer(request.getHeader("Referer"));
|
||||||
|
|
||||||
FileDownloadDto target = tusFileService.selectFileViewOrDownload(fileDownloadDto);
|
TusFileViewOrDownloadVo tusFileViewOrDownloadVo = tusFileService.selectTusFileViewOrDownload(tusFileViewOrDownloadDto);
|
||||||
|
|
||||||
if (target == null) {
|
if (tusFileViewOrDownloadVo == null) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
Path filePath = tusFileService.resolveStoredFilePath(target.getSavePath());
|
Path filePath = tusFileService.resolveStoredFilePath(tusFileViewOrDownloadVo.getSavePath());
|
||||||
|
|
||||||
if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) {
|
if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource resource = new InputStreamResource(Files.newInputStream(filePath));
|
Resource resource = new InputStreamResource(Files.newInputStream(filePath));
|
||||||
String contentType = target.getContentType() == null
|
String contentType = tusFileViewOrDownloadVo.getContentType() == null
|
||||||
? "application/octet-stream"
|
? "application/octet-stream"
|
||||||
: target.getContentType();
|
: tusFileViewOrDownloadVo.getContentType();
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.contentType(MediaType.parseMediaType(contentType))
|
.contentType(MediaType.parseMediaType(contentType))
|
||||||
.contentLength(Files.size(filePath))
|
.contentLength(Files.size(filePath))
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||||
ContentDisposition.attachment()
|
ContentDisposition.attachment()
|
||||||
.filename(target.getOriginName(), StandardCharsets.UTF_8)
|
.filename(tusFileViewOrDownloadVo.getOriginName(), StandardCharsets.UTF_8)
|
||||||
.build()
|
.build()
|
||||||
.toString())
|
.toString())
|
||||||
.body(resource);
|
.body(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "파일 삭제 처리",
|
summary = "파일 삭제 처리"
|
||||||
description = "fileUuid 기준으로 완료된 파일(STATUS = 3)을 논리 삭제 처리합니다. 실제 파일은 삭제하지 않고 DEL_YN = 'Y'만 반영합니다."
|
, description = "fileUuid 기준으로 완료된 파일(STATUS = 3)을 논리 삭제 처리합니다. 실제 파일은 삭제하지 않고 DEL_YN = 'Y'만 반영합니다."
|
||||||
)
|
)
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
public ResponseEntity<ApiResponse<String>> tusFileDelete(
|
public ResponseEntity<ApiResponse<String>> tusFileDelete(
|
||||||
@Valid @RequestBody FileDeleteForm fileDeleteForm
|
@Valid @RequestBody TusFileDeleteForm tusFileDeleteForm
|
||||||
) {
|
) {
|
||||||
boolean deleted = tusFileService.updateFileDelete(fileDeleteForm.toFileDeleteDto());
|
TusFileDeleteVo tusFileDeleteVo = tusFileService.updateTusFileDelete(tusFileDeleteForm.toDto());
|
||||||
|
|
||||||
if (!deleted) {
|
if (!tusFileDeleteVo.isDeleted()) {
|
||||||
return ApiResponse.entity("", ApiResponseCode.CODE_2005, "파일 삭제");
|
return ApiResponse.entity("", ApiResponseCode.CODE_2005, "파일 삭제");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
package com.alist.api.modules.tusFile.dto;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Schema(description = "파일 다운로드 처리 DTO")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class FileDownloadDto {
|
|
||||||
@Schema(description = "파일 상세 PK", example = "1")
|
|
||||||
private Long fileDetailIdx;
|
|
||||||
|
|
||||||
@Schema(description = "파일 마스터 PK", example = "1")
|
|
||||||
private Long fileMasterIdx;
|
|
||||||
|
|
||||||
@Schema(description = "파일 UUID", example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10")
|
|
||||||
private String fileUuid;
|
|
||||||
|
|
||||||
@Schema(description = "원본 파일명", example = "sample.png")
|
|
||||||
private String originName;
|
|
||||||
|
|
||||||
@Schema(description = "Content-Type", example = "image/png")
|
|
||||||
private String contentType;
|
|
||||||
|
|
||||||
@Schema(description = "파일 크기(byte)", example = "102400")
|
|
||||||
private Long sizeBytes;
|
|
||||||
|
|
||||||
private String savePath;
|
|
||||||
private Integer userIdx;
|
|
||||||
private Integer userTokenIdx;
|
|
||||||
private String eventType;
|
|
||||||
private String clientIp;
|
|
||||||
private String userAgent;
|
|
||||||
private String referer;
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Schema(hidden = true)
|
|
||||||
private Integer resultCode;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.alist.api.modules.tusFile.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 파일 삭제 DTO")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileDeleteDto {
|
||||||
|
@Schema(description = "파일 UUID", example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10")
|
||||||
|
private String fileUuid;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private Integer userTokenIdx;
|
||||||
|
}
|
||||||
+1
-1
@@ -5,7 +5,7 @@ import lombok.Setter;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class TusHookDto {
|
public class TusFileHookDto {
|
||||||
private String type;
|
private String type;
|
||||||
private String uploadId;
|
private String uploadId;
|
||||||
private Long size;
|
private Long size;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.alist.api.modules.tusFile.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 파일 목록 조회 DTO")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileListDto {
|
||||||
|
@Schema(description = "파일 마스터 PK", example = "1")
|
||||||
|
private Long fileMasterIdx;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private Integer userTokenIdx;
|
||||||
|
}
|
||||||
+1
-1
@@ -5,7 +5,7 @@ import lombok.Setter;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class FileMoveTaskDto {
|
public class TusFileMoveTaskDto {
|
||||||
private Long fileDetailIdx;
|
private Long fileDetailIdx;
|
||||||
private Long fileMasterIdx;
|
private Long fileMasterIdx;
|
||||||
private String fileUuid;
|
private String fileUuid;
|
||||||
+1
-6
@@ -1,6 +1,5 @@
|
|||||||
package com.alist.api.modules.tusFile.dto;
|
package com.alist.api.modules.tusFile.dto;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -8,7 +7,7 @@ import lombok.Setter;
|
|||||||
@Schema(description = "업로드 인증 토큰 정보")
|
@Schema(description = "업로드 인증 토큰 정보")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class UploadTokenDto {
|
public class TusFileUploadAuthDto {
|
||||||
private Integer userTokenIdx;
|
private Integer userTokenIdx;
|
||||||
|
|
||||||
@Schema(description = "파일 UUID", example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10")
|
@Schema(description = "파일 UUID", example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10")
|
||||||
@@ -28,8 +27,4 @@ public class UploadTokenDto {
|
|||||||
|
|
||||||
@Schema(description = "Content-Type", example = "image/png")
|
@Schema(description = "Content-Type", example = "image/png")
|
||||||
private String contentType;
|
private String contentType;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Schema(hidden = true)
|
|
||||||
private Integer resultCode;
|
|
||||||
}
|
}
|
||||||
+4
-1
@@ -5,7 +5,10 @@ import lombok.Setter;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class FileDeleteDto {
|
public class TusFileUploadCancelDto {
|
||||||
private Integer userTokenIdx;
|
private Integer userTokenIdx;
|
||||||
private String fileUuid;
|
private String fileUuid;
|
||||||
|
|
||||||
|
private Long uploadedBytes;
|
||||||
|
private Long sizeBytes;
|
||||||
}
|
}
|
||||||
+2
-2
@@ -10,7 +10,7 @@ import java.util.List;
|
|||||||
@Schema(description = "TUS 파일 업로드 초기화 응답")
|
@Schema(description = "TUS 파일 업로드 초기화 응답")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class FileUploadDto {
|
public class TusFileUploadInitDto {
|
||||||
@Schema(description = "파일 마스터 PK", example = "1")
|
@Schema(description = "파일 마스터 PK", example = "1")
|
||||||
private Long fileMasterIdx;
|
private Long fileMasterIdx;
|
||||||
|
|
||||||
@@ -42,5 +42,5 @@ public class FileUploadDto {
|
|||||||
private Integer totalCount;
|
private Integer totalCount;
|
||||||
|
|
||||||
@Schema(description = "업로드 파일 항목 목록")
|
@Schema(description = "업로드 파일 항목 목록")
|
||||||
private List<FileUploadItemDto> itemList;
|
private List<TusFileUploadInitItemDto> itemList;
|
||||||
}
|
}
|
||||||
+1
-1
@@ -8,7 +8,7 @@ import lombok.Setter;
|
|||||||
@Schema(description = "TUS 업로드 파일 항목 응답")
|
@Schema(description = "TUS 업로드 파일 항목 응답")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class FileUploadItemDto {
|
public class TusFileUploadInitItemDto {
|
||||||
@Schema(description = "파일 순번", example = "1")
|
@Schema(description = "파일 순번", example = "1")
|
||||||
private Integer fileSeq;
|
private Integer fileSeq;
|
||||||
|
|
||||||
+1
-1
@@ -5,7 +5,7 @@ import lombok.Setter;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class FileUploadMetaDto {
|
public class TusFileUploadMetaDto {
|
||||||
private String fileUuid;
|
private String fileUuid;
|
||||||
private String originName;
|
private String originName;
|
||||||
private Long sizeBytes;
|
private Long sizeBytes;
|
||||||
+1
-5
@@ -5,10 +5,6 @@ import lombok.Setter;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class UploadCancelDto {
|
public class TusFileUploadStatusDto {
|
||||||
private Integer userTokenIdx;
|
|
||||||
private String fileUuid;
|
private String fileUuid;
|
||||||
|
|
||||||
private Long uploadedBytes;
|
|
||||||
private Long sizeBytes;
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.alist.api.modules.tusFile.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 파일 보기/다운로드 조회 DTO")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileViewOrDownloadDto {
|
||||||
|
@Schema(description = "파일 UUID", example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10")
|
||||||
|
private String fileUuid;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private Integer userTokenIdx;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String eventType;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String clientIp;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String userAgent;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String referer;
|
||||||
|
}
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package com.alist.api.modules.tusFile.dto;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Schema(description = "업로드 상태 조회 응답")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class UploadStatusDto {
|
|
||||||
@Schema(description = "파일 UUID", example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10")
|
|
||||||
private String fileUuid;
|
|
||||||
|
|
||||||
@Schema(description = "업로드 상태. PENDING, UPLOADING, DONE, FAILED", example = "UPLOADING")
|
|
||||||
private String status; // PENDING, UPLOADING, DONE, FAILED
|
|
||||||
|
|
||||||
@Schema(description = "업로드 완료 byte", example = "51200")
|
|
||||||
private Long uploadedBytes;
|
|
||||||
|
|
||||||
@Schema(description = "전체 파일 크기 byte", example = "102400")
|
|
||||||
private Long totalBytes;
|
|
||||||
|
|
||||||
@Schema(description = "업로드 진행률", example = "50")
|
|
||||||
private Integer percent;
|
|
||||||
|
|
||||||
@Schema(description = "상태 갱신 시각", example = "2026-05-19T10:30:00")
|
|
||||||
private String updatedAt;
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.alist.api.modules.tusFile.form;
|
|
||||||
|
|
||||||
import com.alist.api.modules.tusFile.dto.FileDeleteDto;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Schema(description = "파일 삭제 요청 폼")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class FileDeleteForm {
|
|
||||||
@Schema(
|
|
||||||
description = "파일 UUID",
|
|
||||||
example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED
|
|
||||||
)
|
|
||||||
@NotBlank(message = "파일 UUID는 필수입니다.")
|
|
||||||
private String fileUuid;
|
|
||||||
|
|
||||||
public FileDeleteDto toFileDeleteDto() {
|
|
||||||
FileDeleteDto fileDeleteDto = new FileDeleteDto();
|
|
||||||
fileDeleteDto.setFileUuid(fileUuid == null ? null : fileUuid.trim());
|
|
||||||
return fileDeleteDto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
package com.alist.api.modules.tusFile.form;
|
|
||||||
|
|
||||||
import com.alist.api.modules.tusFile.dto.FileUploadDto;
|
|
||||||
import com.alist.api.modules.tusFile.dto.FileUploadItemDto;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Schema(description = "TUS 파일 업로드 초기화 요청 폼")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class FileUploadForm {
|
|
||||||
@Schema(
|
|
||||||
description = "파일 카테고리",
|
|
||||||
example = "BOARD",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED
|
|
||||||
)
|
|
||||||
@NotBlank(message = "파일 카테고리는 필수입니다.")
|
|
||||||
private String fileCategory;
|
|
||||||
|
|
||||||
@Schema(description = "업로드 폴더 경로. 미전달 시 / 로 처리됩니다.", example = "/board")
|
|
||||||
private String folderPath;
|
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "업로드 파일 목록",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED
|
|
||||||
)
|
|
||||||
@NotEmpty(message = "업로드 파일 목록은 필수입니다.")
|
|
||||||
@Valid
|
|
||||||
private List<FileUploadItemForm> itemList;
|
|
||||||
|
|
||||||
public FileUploadDto toFileUploadDto() {
|
|
||||||
FileUploadDto fileUploadDto = new FileUploadDto();
|
|
||||||
|
|
||||||
fileUploadDto.setFileCategory(this.fileCategory.trim());
|
|
||||||
fileUploadDto.setFolderPath((this.folderPath == null || this.folderPath.isBlank()) ? "/" : this.folderPath.trim());
|
|
||||||
|
|
||||||
List<FileUploadItemDto> fileUploadItemDtoList = new ArrayList<>();
|
|
||||||
|
|
||||||
int i = 1;
|
|
||||||
for (FileUploadItemForm item : this.itemList) {
|
|
||||||
FileUploadItemDto fileUploadItemDto = new FileUploadItemDto();
|
|
||||||
|
|
||||||
fileUploadItemDto.setFileSeq(i++);
|
|
||||||
fileUploadItemDto.setOriginName(item.getOriginName());
|
|
||||||
fileUploadItemDto.setSizeBytes(item.getSizeBytes());
|
|
||||||
fileUploadItemDto.setContentType(item.getContentType());
|
|
||||||
|
|
||||||
fileUploadItemDtoList.add(fileUploadItemDto);
|
|
||||||
}
|
|
||||||
|
|
||||||
fileUploadDto.setItemList(fileUploadItemDtoList);
|
|
||||||
|
|
||||||
return fileUploadDto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.alist.api.modules.tusFile.form;
|
||||||
|
|
||||||
|
import com.alist.api.modules.tusFile.dto.TusFileDeleteDto;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "파일 삭제 요청 폼")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileDeleteForm {
|
||||||
|
@Schema(
|
||||||
|
description = "파일 UUID"
|
||||||
|
, example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10"
|
||||||
|
, requiredMode = Schema.RequiredMode.REQUIRED
|
||||||
|
)
|
||||||
|
@NotBlank(message = "파일 UUID는 필수입니다.")
|
||||||
|
private String fileUuid;
|
||||||
|
|
||||||
|
public TusFileDeleteDto toDto() {
|
||||||
|
TusFileDeleteDto tusFileDeleteDto = new TusFileDeleteDto();
|
||||||
|
tusFileDeleteDto.setFileUuid(fileUuid == null ? null : fileUuid.trim());
|
||||||
|
return tusFileDeleteDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -10,8 +10,8 @@ import lombok.Setter;
|
|||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class TusHookEventForm {
|
public class TusFileHookEventForm {
|
||||||
@Schema(description = "TUS 업로드 정보")
|
@Schema(description = "TUS 업로드 정보")
|
||||||
@JsonProperty("Upload")
|
@JsonProperty("Upload")
|
||||||
private TusHookUploadForm tusHookUploadForm;
|
private TusFileHookUploadForm tusFileHookUploadForm;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.alist.api.modules.tusFile.form;
|
||||||
|
|
||||||
|
import com.alist.api.modules.tusFile.dto.TusFileHookDto;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 훅 요청 폼")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class TusFileHookForm {
|
||||||
|
@Schema(description = "TUS 훅 이벤트 타입", example = "post-finish")
|
||||||
|
@JsonProperty("Type")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 훅 이벤트 정보")
|
||||||
|
@JsonProperty("Event")
|
||||||
|
private TusFileHookEventForm tusFileHookEventForm;
|
||||||
|
|
||||||
|
public TusFileHookDto toDto() {
|
||||||
|
TusFileHookDto tusFileHookDto = new TusFileHookDto();
|
||||||
|
|
||||||
|
tusFileHookDto.setType(this.type);
|
||||||
|
|
||||||
|
if (this.tusFileHookEventForm == null || this.tusFileHookEventForm.getTusFileHookUploadForm() == null) {
|
||||||
|
return tusFileHookDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
TusFileHookUploadForm upload = this.tusFileHookEventForm.getTusFileHookUploadForm();
|
||||||
|
tusFileHookDto.setUploadId(upload.getId());
|
||||||
|
tusFileHookDto.setSize(upload.getSize());
|
||||||
|
tusFileHookDto.setOffset(upload.getOffset());
|
||||||
|
|
||||||
|
if (upload.getMetaData() != null) {
|
||||||
|
tusFileHookDto.setFileUuid(upload.getMetaData().get("fileUuid"));
|
||||||
|
tusFileHookDto.setFilename(upload.getMetaData().get("filename"));
|
||||||
|
tusFileHookDto.setFiletype(upload.getMetaData().get("filetype"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tusFileHookDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -12,7 +12,7 @@ import java.util.Map;
|
|||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class TusHookUploadForm {
|
public class TusFileHookUploadForm {
|
||||||
@Schema(description = "TUS 업로드 ID", example = "018f6f2d7b5c7d499c3a8c0f4f9f9f10")
|
@Schema(description = "TUS 업로드 ID", example = "018f6f2d7b5c7d499c3a8c0f4f9f9f10")
|
||||||
@JsonProperty("ID")
|
@JsonProperty("ID")
|
||||||
private String id;
|
private String id;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.alist.api.modules.tusFile.form;
|
||||||
|
|
||||||
|
import com.alist.api.modules.tusFile.dto.TusFileUploadCancelDto;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "업로드 취소 요청 폼")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileUploadCancelForm {
|
||||||
|
@Schema(
|
||||||
|
description = "파일 UUID"
|
||||||
|
, example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10"
|
||||||
|
, requiredMode = Schema.RequiredMode.REQUIRED
|
||||||
|
)
|
||||||
|
@NotBlank(message = "파일 UUID는 필수입니다.")
|
||||||
|
private String fileUuid;
|
||||||
|
|
||||||
|
public TusFileUploadCancelDto toDto() {
|
||||||
|
TusFileUploadCancelDto tusFileUploadCancelDto = new TusFileUploadCancelDto();
|
||||||
|
tusFileUploadCancelDto.setFileUuid(this.fileUuid == null ? null : this.fileUuid.trim());
|
||||||
|
return tusFileUploadCancelDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.alist.api.modules.tusFile.form;
|
||||||
|
|
||||||
|
import com.alist.api.modules.tusFile.dto.TusFileUploadInitDto;
|
||||||
|
import com.alist.api.modules.tusFile.dto.TusFileUploadInitItemDto;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 파일 업로드 초기화 요청 폼")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileUploadInitForm {
|
||||||
|
@Schema(
|
||||||
|
description = "파일 카테고리"
|
||||||
|
, example = "BOARD"
|
||||||
|
, requiredMode = Schema.RequiredMode.REQUIRED
|
||||||
|
)
|
||||||
|
@NotBlank(message = "파일 카테고리는 필수입니다.")
|
||||||
|
private String fileCategory;
|
||||||
|
|
||||||
|
@Schema(description = "업로드 폴더 경로. 미전달 시 / 로 처리됩니다.", example = "/board")
|
||||||
|
private String folderPath;
|
||||||
|
|
||||||
|
@Schema(
|
||||||
|
description = "업로드 파일 목록"
|
||||||
|
, requiredMode = Schema.RequiredMode.REQUIRED
|
||||||
|
)
|
||||||
|
@NotEmpty(message = "업로드 파일 목록은 필수입니다.")
|
||||||
|
@Valid
|
||||||
|
private List<TusFileUploadInitItemForm> itemList;
|
||||||
|
|
||||||
|
public TusFileUploadInitDto toDto() {
|
||||||
|
TusFileUploadInitDto tusFileUploadInitDto = new TusFileUploadInitDto();
|
||||||
|
|
||||||
|
tusFileUploadInitDto.setFileCategory(this.fileCategory.trim());
|
||||||
|
tusFileUploadInitDto.setFolderPath((this.folderPath == null || this.folderPath.isBlank()) ? "/" : this.folderPath.trim());
|
||||||
|
|
||||||
|
List<TusFileUploadInitItemDto> tusFileUploadInitItemDtoList = new ArrayList<>();
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
for (TusFileUploadInitItemForm item : this.itemList) {
|
||||||
|
TusFileUploadInitItemDto tusFileUploadInitItemDto = new TusFileUploadInitItemDto();
|
||||||
|
|
||||||
|
tusFileUploadInitItemDto.setFileSeq(i++);
|
||||||
|
tusFileUploadInitItemDto.setOriginName(item.getOriginName());
|
||||||
|
tusFileUploadInitItemDto.setSizeBytes(item.getSizeBytes());
|
||||||
|
tusFileUploadInitItemDto.setContentType(item.getContentType());
|
||||||
|
|
||||||
|
tusFileUploadInitItemDtoList.add(tusFileUploadInitItemDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
tusFileUploadInitDto.setItemList(tusFileUploadInitItemDtoList);
|
||||||
|
|
||||||
|
return tusFileUploadInitDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-7
@@ -10,19 +10,19 @@ import lombok.Setter;
|
|||||||
@Schema(description = "TUS 업로드 파일 항목")
|
@Schema(description = "TUS 업로드 파일 항목")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class FileUploadItemForm {
|
public class TusFileUploadInitItemForm {
|
||||||
@Schema(
|
@Schema(
|
||||||
description = "원본 파일명",
|
description = "원본 파일명"
|
||||||
example = "sample.png",
|
, example = "sample.png"
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED
|
, requiredMode = Schema.RequiredMode.REQUIRED
|
||||||
)
|
)
|
||||||
@NotBlank(message = "원본 파일명은 필수입니다.")
|
@NotBlank(message = "원본 파일명은 필수입니다.")
|
||||||
private String originName;
|
private String originName;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description = "파일 크기(byte)",
|
description = "파일 크기(byte)"
|
||||||
example = "102400",
|
, example = "102400"
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED
|
, requiredMode = Schema.RequiredMode.REQUIRED
|
||||||
)
|
)
|
||||||
@NotNull(message = "파일 크기는 필수입니다.")
|
@NotNull(message = "파일 크기는 필수입니다.")
|
||||||
@Positive(message = "파일 크기는 0보다 커야 합니다.")
|
@Positive(message = "파일 크기는 0보다 커야 합니다.")
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.alist.api.modules.tusFile.form;
|
||||||
|
|
||||||
|
import com.alist.api.modules.tusFile.dto.TusFileUploadStatusDto;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "업로드 상태 조회 요청 폼")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileUploadStatusForm {
|
||||||
|
@Schema(
|
||||||
|
description = "파일 UUID"
|
||||||
|
, example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10"
|
||||||
|
, requiredMode = Schema.RequiredMode.REQUIRED
|
||||||
|
)
|
||||||
|
@NotBlank(message = "파일 UUID는 필수입니다.")
|
||||||
|
private String fileUuid;
|
||||||
|
|
||||||
|
public TusFileUploadStatusDto toDto() {
|
||||||
|
TusFileUploadStatusDto tusFileUploadStatusDto = new TusFileUploadStatusDto();
|
||||||
|
tusFileUploadStatusDto.setFileUuid(this.fileUuid == null ? null : this.fileUuid.trim());
|
||||||
|
return tusFileUploadStatusDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package com.alist.api.modules.tusFile.form;
|
|
||||||
|
|
||||||
import com.alist.api.modules.tusFile.dto.TusHookDto;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Schema(description = "TUS 훅 요청 폼")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class TusHookForm {
|
|
||||||
@Schema(description = "TUS 훅 이벤트 타입", example = "post-finish")
|
|
||||||
@JsonProperty("Type")
|
|
||||||
private String type;
|
|
||||||
|
|
||||||
@Schema(description = "TUS 훅 이벤트 정보")
|
|
||||||
@JsonProperty("Event")
|
|
||||||
private TusHookEventForm tusHookEventForm;
|
|
||||||
|
|
||||||
public TusHookDto toTusHookDto() {
|
|
||||||
TusHookDto tusHookDto = new TusHookDto();
|
|
||||||
|
|
||||||
tusHookDto.setType(this.type);
|
|
||||||
|
|
||||||
if (this.tusHookEventForm == null || this.tusHookEventForm.getTusHookUploadForm() == null) {
|
|
||||||
return tusHookDto;
|
|
||||||
}
|
|
||||||
|
|
||||||
TusHookUploadForm upload = this.tusHookEventForm.getTusHookUploadForm();
|
|
||||||
tusHookDto.setUploadId(upload.getId());
|
|
||||||
tusHookDto.setSize(upload.getSize());
|
|
||||||
tusHookDto.setOffset(upload.getOffset());
|
|
||||||
|
|
||||||
if (upload.getMetaData() != null) {
|
|
||||||
tusHookDto.setFileUuid(upload.getMetaData().get("fileUuid"));
|
|
||||||
tusHookDto.setFilename(upload.getMetaData().get("filename"));
|
|
||||||
tusHookDto.setFiletype(upload.getMetaData().get("filetype"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tusHookDto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package com.alist.api.modules.tusFile.form;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Schema(description = "업로드 취소 요청 폼")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class UploadCancelForm {
|
|
||||||
@Schema(
|
|
||||||
description = "파일 UUID",
|
|
||||||
example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED
|
|
||||||
)
|
|
||||||
@NotBlank(message = "파일 UUID는 필수입니다.")
|
|
||||||
private String fileUuid;
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.alist.api.modules.tusFile.form;
|
|
||||||
|
|
||||||
import com.alist.api.modules.tusFile.dto.UploadStatusDto;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Schema(description = "업로드 상태 조회 요청 폼")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class UploadStatusForm {
|
|
||||||
@Schema(
|
|
||||||
description = "파일 UUID",
|
|
||||||
example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED
|
|
||||||
)
|
|
||||||
@NotBlank(message = "파일 UUID는 필수입니다.")
|
|
||||||
private String fileUuid;
|
|
||||||
|
|
||||||
public UploadStatusDto toUploadStatusDto() {
|
|
||||||
UploadStatusDto uploadStatusDto = new UploadStatusDto();
|
|
||||||
uploadStatusDto.setFileUuid(this.fileUuid == null ? null : this.fileUuid.trim());
|
|
||||||
return uploadStatusDto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +1,56 @@
|
|||||||
package com.alist.api.modules.tusFile.mapper;
|
package com.alist.api.modules.tusFile.mapper;
|
||||||
|
|
||||||
import com.alist.api.modules.tusFile.dto.*;
|
import com.alist.api.modules.tusFile.dto.*;
|
||||||
|
import com.alist.api.modules.tusFile.vo.TusFileListItemVo;
|
||||||
|
import com.alist.api.modules.tusFile.vo.TusFileUploadCancelProgressVo;
|
||||||
|
import com.alist.api.modules.tusFile.vo.TusFileViewOrDownloadVo;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface TusFileMapper {
|
public interface TusFileMapper {
|
||||||
void insertFileMasterInit(FileUploadDto fileUploadDto);
|
void insertTusFileUploadInitMaster(TusFileUploadInitDto tusFileUploadInitDto);
|
||||||
|
|
||||||
void insertFileDetailInit(FileUploadItemDto item);
|
void insertTusFileUploadInitDetail(TusFileUploadInitItemDto tusFileUploadInitItemDto);
|
||||||
|
|
||||||
int selectFileDetailCountByFileUuidUserToKenIdx(UploadTokenDto uploadTokenDto);
|
int selectTusFileUploadAuthCount(TusFileUploadAuthDto tusFileUploadAuthDto);
|
||||||
|
|
||||||
void insertFileUploadEventLog(TusHookDto tusHookDto);
|
void insertTusFileHookEventLog(TusFileHookDto tusFileHookDto);
|
||||||
|
|
||||||
void updateFileDetailStatus(TusHookDto tusHookDto);
|
void updateTusFileHookDetailStatus(TusFileHookDto tusFileHookDto);
|
||||||
|
|
||||||
void updateFileMasterAggregateByFileUuid(String fileUuid);
|
void updateFileMasterAggregateByFileUuid(String fileUuid);
|
||||||
|
|
||||||
FileUploadMetaDto selectFileUploadMetaByFileUuid(String fileUuid);
|
TusFileUploadMetaDto selectTusFileUploadMeta(String fileUuid);
|
||||||
|
|
||||||
void updateTusUploadIdIfNull(FileUploadMetaDto fileUploadMetaDto);
|
void updateTusFileUploadIdIfNull(TusFileUploadMetaDto tusFileUploadMetaDto);
|
||||||
|
|
||||||
void updateFileDetailCanceledByFileUuid(String fileUuid);
|
void updateFileDetailCanceledByFileUuid(String fileUuid);
|
||||||
|
|
||||||
int selectFileDetailCountByFileUuidAndUserToKenIdx(UploadCancelDto uploadCancelDto);
|
int selectTusFileUploadCancelCount(TusFileUploadCancelDto tusFileUploadCancelDto);
|
||||||
|
|
||||||
int updateFileDetailCanceledByFileUuidAndUserTokenIdx(UploadCancelDto uploadCancelDto);
|
TusFileUploadCancelProgressVo selectTusFileUploadCancelProgress(TusFileUploadCancelDto tusFileUploadCancelDto);
|
||||||
|
|
||||||
UploadCancelDto selectUploadProgressByFileUuid(UploadCancelDto uploadCancelDto);
|
TusFileMoveTaskDto selectTusFileMoveTask(String fileUuid);
|
||||||
|
|
||||||
FileMoveTaskDto selectMoveTaskByFileUuid(String fileUuid);
|
int updateTusFileMoveSuccess(TusFileMoveTaskDto tusFileMoveTaskDto);
|
||||||
|
|
||||||
int updateFileMoveSuccess(FileMoveTaskDto task);
|
int updateTusFileMovePending(TusFileMoveTaskDto tusFileMoveTaskDto);
|
||||||
|
|
||||||
int updateFileMovePendingByFileUuid(FileMoveTaskDto task);
|
List<TusFileListItemVo> selectTusFileList(TusFileListDto tusFileListDto);
|
||||||
|
|
||||||
List<FileDownloadItemDto> selectFileDownloadListByFileMasterIdx(FileDownloadDto fileDownloadDto);
|
TusFileViewOrDownloadVo selectTusFileViewOrDownload(TusFileViewOrDownloadDto tusFileViewOrDownloadDto);
|
||||||
|
|
||||||
FileDownloadDto selectFileDetailByFileUuid(FileDownloadDto fileDownloadDto);
|
void insertTusFileViewOrDownloadEventLog(TusFileViewOrDownloadVo tusFileViewOrDownloadVo);
|
||||||
|
|
||||||
void insertFileDownloadEventLog(FileDownloadDto fileDetailInfo);
|
int selectTusFileDeleteTargetCount(TusFileDeleteDto tusFileDeleteDto);
|
||||||
|
|
||||||
int selectFileDeleteTargetCount(FileDeleteDto fileDeleteDto);
|
int updateTusFileDetailDelete(TusFileDeleteDto tusFileDeleteDto);
|
||||||
|
|
||||||
int updateFileDetailDeleteByFileUuid(FileDeleteDto fileDeleteDto);
|
int updateTusFileMasterDelete(TusFileDeleteDto tusFileDeleteDto);
|
||||||
|
|
||||||
int updateFileMasterDeleteByFileUuid(FileDeleteDto fileDeleteDto);
|
|
||||||
|
|
||||||
Integer selectUserIdxByUserTokenIdx(Integer userTokenIdx);
|
Integer selectUserIdxByUserTokenIdx(Integer userTokenIdx);
|
||||||
|
|
||||||
|
int updateTusFileUploadCancel(TusFileUploadCancelDto tusFileUploadCancelDto);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.alist.api.common.utils.SecurityUtil;
|
|||||||
import com.alist.api.config.jwt.JwtTokenProvider;
|
import com.alist.api.config.jwt.JwtTokenProvider;
|
||||||
import com.alist.api.modules.tusFile.dto.*;
|
import com.alist.api.modules.tusFile.dto.*;
|
||||||
import com.alist.api.modules.tusFile.mapper.TusFileMapper;
|
import com.alist.api.modules.tusFile.mapper.TusFileMapper;
|
||||||
|
import com.alist.api.modules.tusFile.vo.*;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.data.redis.core.HashOperations;
|
import org.springframework.data.redis.core.HashOperations;
|
||||||
@@ -19,10 +20,7 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.HexFormat;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@@ -57,70 +55,102 @@ public class TusFileService {
|
|||||||
|
|
||||||
/*파일 초기화 작업*/
|
/*파일 초기화 작업*/
|
||||||
@Transactional
|
@Transactional
|
||||||
public FileUploadDto insertFileInit(FileUploadDto fileUploadDto) {
|
public TusFileUploadInitVo insertTusFileUploadInit(TusFileUploadInitDto tusFileUploadInitDto) {
|
||||||
fileUploadDto.setStatus(0);
|
tusFileUploadInitDto.setStatus(0);
|
||||||
fileUploadDto.setTotalCount(fileUploadDto.getItemList().size());
|
tusFileUploadInitDto.setTotalCount(tusFileUploadInitDto.getItemList().size());
|
||||||
|
|
||||||
tusFileMapper.insertFileMasterInit(fileUploadDto);
|
tusFileMapper.insertTusFileUploadInitMaster(tusFileUploadInitDto);
|
||||||
fileUploadDto.setTusEndpoint(tusEndpoint);
|
tusFileUploadInitDto.setTusEndpoint(tusEndpoint);
|
||||||
|
|
||||||
if (fileUploadDto.getItemList() == null || fileUploadDto.getItemList().isEmpty()) {
|
if (tusFileUploadInitDto.getItemList() == null || tusFileUploadInitDto.getItemList().isEmpty()) {
|
||||||
return fileUploadDto;
|
return toTusFileUploadInitVo(tusFileUploadInitDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FileUploadItemDto item : fileUploadDto.getItemList()) {
|
for (TusFileUploadInitItemDto tusFileUploadInitItemDto : tusFileUploadInitDto.getItemList()) {
|
||||||
item.setFileMasterIdx(fileUploadDto.getFileMasterIdx());
|
tusFileUploadInitItemDto.setFileMasterIdx(tusFileUploadInitDto.getFileMasterIdx());
|
||||||
item.setFileUuid(UUID.randomUUID().toString());
|
tusFileUploadInitItemDto.setFileUuid(UUID.randomUUID().toString());
|
||||||
item.setUploadToken(jwtTokenProvider.createUploadToken(fileUploadDto.getUserTokenIdx()));
|
tusFileUploadInitItemDto.setUploadToken(jwtTokenProvider.createUploadToken(tusFileUploadInitDto.getUserTokenIdx()));
|
||||||
item.setUserIdx(fileUploadDto.getUserIdx());
|
tusFileUploadInitItemDto.setUserIdx(tusFileUploadInitDto.getUserIdx());
|
||||||
item.setStatus(0); // PENDING
|
tusFileUploadInitItemDto.setStatus(0);
|
||||||
tusFileMapper.insertFileDetailInit(item);
|
|
||||||
|
tusFileMapper.insertTusFileUploadInitDetail(tusFileUploadInitItemDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileUploadDto;
|
return toTusFileUploadInitVo(tusFileUploadInitDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TusFileUploadInitVo toTusFileUploadInitVo(TusFileUploadInitDto tusFileUploadInitDto) {
|
||||||
|
TusFileUploadInitVo tusFileUploadInitVo = new TusFileUploadInitVo();
|
||||||
|
|
||||||
|
tusFileUploadInitVo.setFileMasterIdx(tusFileUploadInitDto.getFileMasterIdx());
|
||||||
|
tusFileUploadInitVo.setTusEndpoint(tusFileUploadInitDto.getTusEndpoint());
|
||||||
|
|
||||||
|
List<TusFileUploadInitItemVo> tusFileUploadInitItemVoList = new ArrayList<>();
|
||||||
|
|
||||||
|
if (tusFileUploadInitDto.getItemList() != null) {
|
||||||
|
for (TusFileUploadInitItemDto tusFileUploadInitItemDto : tusFileUploadInitDto.getItemList()) {
|
||||||
|
TusFileUploadInitItemVo tusFileUploadInitItemVo = new TusFileUploadInitItemVo();
|
||||||
|
|
||||||
|
tusFileUploadInitItemVo.setFileSeq(tusFileUploadInitItemDto.getFileSeq());
|
||||||
|
tusFileUploadInitItemVo.setFileUuid(tusFileUploadInitItemDto.getFileUuid());
|
||||||
|
tusFileUploadInitItemVo.setUploadToken(tusFileUploadInitItemDto.getUploadToken());
|
||||||
|
tusFileUploadInitItemVo.setOriginName(tusFileUploadInitItemDto.getOriginName());
|
||||||
|
tusFileUploadInitItemVo.setSizeBytes(tusFileUploadInitItemDto.getSizeBytes());
|
||||||
|
tusFileUploadInitItemVo.setContentType(tusFileUploadInitItemDto.getContentType());
|
||||||
|
|
||||||
|
tusFileUploadInitItemVoList.add(tusFileUploadInitItemVo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tusFileUploadInitVo.setItemList(tusFileUploadInitItemVoList);
|
||||||
|
|
||||||
|
return tusFileUploadInitVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*업로드 권한 체크*/
|
/*업로드 권한 체크*/
|
||||||
public UploadTokenDto isUploadTokenCheck(UploadTokenDto uploadTokenDto) {
|
public TusFileUploadAuthVo selectTusFileUploadAuth(TusFileUploadAuthDto tusFileUploadAuthDto) {
|
||||||
if (!jwtTokenProvider.validateToken(uploadTokenDto.getUploadToken())) {
|
TusFileUploadAuthVo tusFileUploadAuthVo = new TusFileUploadAuthVo();
|
||||||
uploadTokenDto.setResultCode(401);
|
|
||||||
return uploadTokenDto;
|
if (!jwtTokenProvider.validateToken(tusFileUploadAuthDto.getUploadToken())) {
|
||||||
|
tusFileUploadAuthVo.setResultCode(401);
|
||||||
|
return tusFileUploadAuthVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!jwtTokenProvider.hasUploadScope(uploadTokenDto.getUploadToken())) {
|
if (!jwtTokenProvider.hasUploadScope(tusFileUploadAuthDto.getUploadToken())) {
|
||||||
uploadTokenDto.setResultCode(403);
|
tusFileUploadAuthVo.setResultCode(403);
|
||||||
return uploadTokenDto;
|
return tusFileUploadAuthVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
uploadTokenDto.setUserTokenIdx(Integer.parseInt(jwtTokenProvider.getUserTokenIdx(uploadTokenDto.getUploadToken())));
|
tusFileUploadAuthDto.setUserTokenIdx(Integer.parseInt(jwtTokenProvider.getUserTokenIdx(tusFileUploadAuthDto.getUploadToken())));
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
uploadTokenDto.setResultCode(401);
|
tusFileUploadAuthVo.setResultCode(401);
|
||||||
return uploadTokenDto;
|
return tusFileUploadAuthVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyTusMeta(uploadTokenDto);
|
applyTusMeta(tusFileUploadAuthDto);
|
||||||
|
|
||||||
String cacheKey = buildAuthCacheKey(uploadTokenDto);
|
String cacheKey = buildAuthCacheKey(tusFileUploadAuthDto);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String cached = stringRedisTemplate.opsForValue().get(cacheKey);
|
String cached = stringRedisTemplate.opsForValue().get(cacheKey);
|
||||||
if (cached != null) {
|
if (cached != null) {
|
||||||
try {
|
try {
|
||||||
uploadTokenDto.setResultCode(Integer.parseInt(cached));
|
tusFileUploadAuthVo.setResultCode(Integer.parseInt(cached));
|
||||||
return uploadTokenDto;
|
return tusFileUploadAuthVo;
|
||||||
} catch (NumberFormatException parseEx) {
|
} catch (NumberFormatException parseEx) {
|
||||||
log.warn("uploadAuth cache parse fail. key={}, value={}", cacheKey, cached);
|
log.warn("uploadAuth cache parse fail. key={}, value={}", cacheKey, cached);
|
||||||
stringRedisTemplate.delete(cacheKey); // 오염 캐시 정리
|
stringRedisTemplate.delete(cacheKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception redisGetEx) {
|
} catch (Exception redisGetEx) {
|
||||||
log.warn("uploadAuth cache get fail. fallback DB. key={}", cacheKey, redisGetEx);
|
log.warn("uploadAuth cache get fail. fallback DB. key={}", cacheKey, redisGetEx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int isOk = tusFileMapper.selectFileDetailCountByFileUuidUserToKenIdx(uploadTokenDto);
|
int tusFileUploadAuthCount = tusFileMapper.selectTusFileUploadAuthCount(tusFileUploadAuthDto);
|
||||||
int resultCode = (isOk > 0) ? 200 : 403;
|
int resultCode = (tusFileUploadAuthCount > 0) ? 200 : 403;
|
||||||
uploadTokenDto.setResultCode(resultCode);
|
|
||||||
|
tusFileUploadAuthVo.setResultCode(resultCode);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stringRedisTemplate.opsForValue().set(
|
stringRedisTemplate.opsForValue().set(
|
||||||
@@ -132,16 +162,16 @@ public class TusFileService {
|
|||||||
log.warn("uploadAuth cache set fail. key={}, resultCode={}", cacheKey, resultCode, redisSetEx);
|
log.warn("uploadAuth cache set fail. key={}, resultCode={}", cacheKey, resultCode, redisSetEx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return uploadTokenDto;
|
return tusFileUploadAuthVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyTusMeta(UploadTokenDto dto) {
|
private void applyTusMeta(TusFileUploadAuthDto tusFileUploadAuthDto) {
|
||||||
String len = dto.getUploadLengthRaw();
|
String len = tusFileUploadAuthDto.getUploadLengthRaw();
|
||||||
if (len != null && !len.isBlank()) {
|
if (len != null && !len.isBlank()) {
|
||||||
try { dto.setSizeBytes(Long.parseLong(len.trim())); } catch (Exception ignored) {}
|
try { tusFileUploadAuthDto.setSizeBytes(Long.parseLong(len.trim())); } catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
String raw = dto.getUploadMetadataRaw();
|
String raw = tusFileUploadAuthDto.getUploadMetadataRaw();
|
||||||
if (raw == null || raw.isBlank()) return;
|
if (raw == null || raw.isBlank()) return;
|
||||||
|
|
||||||
for (String part : raw.split(",")) {
|
for (String part : raw.split(",")) {
|
||||||
@@ -158,20 +188,22 @@ public class TusFileService {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("filename".equals(key)) dto.setOriginName(decoded);
|
if ("filename".equals(key)) tusFileUploadAuthDto.setOriginName(decoded);
|
||||||
else if ("filetype".equals(key)) dto.setContentType(decoded);
|
else if ("filetype".equals(key)) tusFileUploadAuthDto.setContentType(decoded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UploadStatusDto getUploadStatus(UploadStatusDto uploadStatusDto) {
|
public TusFileUploadStatusVo loadTusFileUploadStatus(TusFileUploadStatusDto tusFileUploadStatusDto) {
|
||||||
String key = buildUploadStatusKey(uploadStatusDto.getFileUuid());
|
String key = buildUploadStatusKey(tusFileUploadStatusDto.getFileUuid());
|
||||||
Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(key);
|
Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(key);
|
||||||
|
|
||||||
if (map.isEmpty()) {
|
if (map.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String fileUuid = (String) map.getOrDefault("fileUuid", uploadStatusDto.getFileUuid());
|
TusFileUploadStatusVo tusFileUploadStatusVo = new TusFileUploadStatusVo();
|
||||||
|
|
||||||
|
String fileUuid = (String) map.getOrDefault("fileUuid", tusFileUploadStatusDto.getFileUuid());
|
||||||
String status = (String) map.getOrDefault("status", "PENDING");
|
String status = (String) map.getOrDefault("status", "PENDING");
|
||||||
long uploadedBytes = parseLong(map.get("uploadedBytes"));
|
long uploadedBytes = parseLong(map.get("uploadedBytes"));
|
||||||
long totalBytes = parseLong(map.get("totalBytes"));
|
long totalBytes = parseLong(map.get("totalBytes"));
|
||||||
@@ -184,19 +216,19 @@ public class TusFileService {
|
|||||||
updatedAt = Instant.now().toString();
|
updatedAt = Instant.now().toString();
|
||||||
|
|
||||||
saveCanceledStatusRedis(fileUuid, uploadedBytes, totalBytes);
|
saveCanceledStatusRedis(fileUuid, uploadedBytes, totalBytes);
|
||||||
fileMapper.updateFileDetailCanceledByFileUuid(fileUuid);
|
tusFileMapper.updateFileDetailCanceledByFileUuid(fileUuid);
|
||||||
fileMapper.updateFileMasterAggregateByFileUuid(fileUuid);
|
tusFileMapper.updateFileMasterAggregateByFileUuid(fileUuid);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uploadStatusDto.setFileUuid(fileUuid);
|
tusFileUploadStatusVo.setFileUuid(fileUuid);
|
||||||
uploadStatusDto.setStatus(status);
|
tusFileUploadStatusVo.setStatus(status);
|
||||||
uploadStatusDto.setUploadedBytes(uploadedBytes);
|
tusFileUploadStatusVo.setUploadedBytes(uploadedBytes);
|
||||||
uploadStatusDto.setTotalBytes(totalBytes);
|
tusFileUploadStatusVo.setTotalBytes(totalBytes);
|
||||||
uploadStatusDto.setPercent(percent);
|
tusFileUploadStatusVo.setPercent(percent);
|
||||||
uploadStatusDto.setUpdatedAt(updatedAt);
|
tusFileUploadStatusVo.setUpdatedAt(updatedAt);
|
||||||
|
|
||||||
return uploadStatusDto;
|
return tusFileUploadStatusVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isStaleUploading(String status, String updatedAt) {
|
private boolean isStaleUploading(String status, String updatedAt) {
|
||||||
@@ -222,23 +254,23 @@ public class TusFileService {
|
|||||||
|
|
||||||
/*db에 상태값 저장*/
|
/*db에 상태값 저장*/
|
||||||
@Transactional
|
@Transactional
|
||||||
public boolean updateFileUploadStatus(TusHookDto tusHookDto) {
|
public boolean updateTusFileHook(TusFileHookDto tusFileHookDto) {
|
||||||
if (tusHookDto == null || tusHookDto.getFileUuid() == null || tusHookDto.getFileUuid().isBlank()) {
|
if (tusFileHookDto == null || tusFileHookDto.getFileUuid() == null || tusFileHookDto.getFileUuid().isBlank()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String fileUuid = tusHookDto.getFileUuid().trim();
|
String fileUuid = tusFileHookDto.getFileUuid().trim();
|
||||||
String type = tusHookDto.getType() == null ? "" : tusHookDto.getType().trim().toLowerCase();
|
String type = tusFileHookDto.getType() == null ? "" : tusFileHookDto.getType().trim().toLowerCase();
|
||||||
String uploadId = tusHookDto.getUploadId() == null ? "" : tusHookDto.getUploadId().trim();
|
String uploadId = tusFileHookDto.getUploadId() == null ? "" : tusFileHookDto.getUploadId().trim();
|
||||||
long offset = tusHookDto.getOffset() == null ? 0L : tusHookDto.getOffset();
|
long offset = tusFileHookDto.getOffset() == null ? 0L : tusFileHookDto.getOffset();
|
||||||
long size = tusHookDto.getSize() == null ? 0L : tusHookDto.getSize();
|
long size = tusFileHookDto.getSize() == null ? 0L : tusFileHookDto.getSize();
|
||||||
|
|
||||||
tusFileMapper.insertFileUploadEventLog(tusHookDto);
|
tusFileMapper.insertTusFileHookEventLog(tusFileHookDto);
|
||||||
|
|
||||||
FileUploadMetaDto fileUploadMetaInfo = tusFileMapper.selectFileUploadMetaByFileUuid(fileUuid);
|
TusFileUploadMetaDto fileUploadMetaInfo = tusFileMapper.selectTusFileUploadMeta(fileUuid);
|
||||||
if (fileUploadMetaInfo == null) return true;
|
if (fileUploadMetaInfo == null) return true;
|
||||||
|
|
||||||
if (isMetadataMismatch(fileUploadMetaInfo, tusHookDto)) {
|
if (isMetadataMismatch(fileUploadMetaInfo, tusFileHookDto)) {
|
||||||
tusFileMapper.updateFileDetailCanceledByFileUuid(fileUuid);
|
tusFileMapper.updateFileDetailCanceledByFileUuid(fileUuid);
|
||||||
tusFileMapper.updateFileMasterAggregateByFileUuid(fileUuid);
|
tusFileMapper.updateFileMasterAggregateByFileUuid(fileUuid);
|
||||||
saveCanceledStatusRedis(fileUuid, offset, size);
|
saveCanceledStatusRedis(fileUuid, offset, size);
|
||||||
@@ -247,12 +279,12 @@ public class TusFileService {
|
|||||||
|
|
||||||
if (!uploadId.isBlank()) {
|
if (!uploadId.isBlank()) {
|
||||||
if (fileUploadMetaInfo.getTusUploadId() == null || fileUploadMetaInfo.getTusUploadId().isBlank()) {
|
if (fileUploadMetaInfo.getTusUploadId() == null || fileUploadMetaInfo.getTusUploadId().isBlank()) {
|
||||||
FileUploadMetaDto fileUploadMetaDto = new FileUploadMetaDto();
|
TusFileUploadMetaDto tusFileUploadMetaDto = new TusFileUploadMetaDto();
|
||||||
fileUploadMetaDto.setFileUuid(fileUuid);
|
tusFileUploadMetaDto.setFileUuid(fileUuid);
|
||||||
fileUploadMetaDto.setTusUploadId(uploadId);
|
tusFileUploadMetaDto.setTusUploadId(uploadId);
|
||||||
tusFileMapper.updateTusUploadIdIfNull(fileUploadMetaDto);
|
tusFileMapper.updateTusFileUploadIdIfNull(tusFileUploadMetaDto);
|
||||||
|
|
||||||
fileUploadMetaInfo = tusFileMapper.selectFileUploadMetaByFileUuid(fileUuid);
|
fileUploadMetaInfo = tusFileMapper.selectTusFileUploadMeta(fileUuid);
|
||||||
}
|
}
|
||||||
if (fileUploadMetaInfo.getTusUploadId() == null || fileUploadMetaInfo.getTusUploadId().isBlank()
|
if (fileUploadMetaInfo.getTusUploadId() == null || fileUploadMetaInfo.getTusUploadId().isBlank()
|
||||||
|| !fileUploadMetaInfo.getTusUploadId().equals(uploadId)) {
|
|| !fileUploadMetaInfo.getTusUploadId().equals(uploadId)) {
|
||||||
@@ -280,8 +312,8 @@ public class TusFileService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tusHookDto.setUploadedBytes(null);
|
tusFileHookDto.setUploadedBytes(null);
|
||||||
tusHookDto.setStatus(1); // UPLOADING
|
tusFileHookDto.setStatus(1); // UPLOADING
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "post-receive":
|
case "post-receive":
|
||||||
@@ -290,13 +322,13 @@ public class TusFileService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tusHookDto.setUploadedBytes(null);
|
tusFileHookDto.setUploadedBytes(null);
|
||||||
tusHookDto.setStatus(1); // UPLOADING
|
tusFileHookDto.setStatus(1); // UPLOADING
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "post-finish":
|
case "post-finish":
|
||||||
tusHookDto.setUploadedBytes(size);
|
tusFileHookDto.setUploadedBytes(size);
|
||||||
tusHookDto.setStatus(3); // DONE
|
tusFileHookDto.setStatus(3); // DONE
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "post-terminate":
|
case "post-terminate":
|
||||||
@@ -304,31 +336,31 @@ public class TusFileService {
|
|||||||
if (currentStatus != null && currentStatus == 3) {
|
if (currentStatus != null && currentStatus == 3) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
tusHookDto.setUploadedBytes(offset);
|
tusFileHookDto.setUploadedBytes(offset);
|
||||||
tusHookDto.setStatus(5); // CANCELED
|
tusFileHookDto.setStatus(5); // CANCELED
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tusHookDto.getStatus() == 1 && currentStatus != null && currentStatus >= 3) {
|
if (tusFileHookDto.getStatus() == 1 && currentStatus != null && currentStatus >= 3) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean shouldUpdateDetail = !"post-receive".equals(type);
|
boolean shouldUpdateDetail = !"post-receive".equals(type);
|
||||||
|
|
||||||
if (shouldUpdateDetail) {
|
if (shouldUpdateDetail) {
|
||||||
tusFileMapper.updateFileDetailStatus(tusHookDto);
|
tusFileMapper.updateTusFileHookDetailStatus(tusFileHookDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("post-finish".equals(type) || "post-terminate".equals(type)) {
|
if ("post-finish".equals(type) || "post-terminate".equals(type)) {
|
||||||
tusFileMapper.updateFileMasterAggregateByFileUuid(tusHookDto.getFileUuid());
|
tusFileMapper.updateFileMasterAggregateByFileUuid(tusFileHookDto.getFileUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("post-finish".equals(type)) {
|
if ("post-finish".equals(type)) {
|
||||||
try {
|
try {
|
||||||
tryMoveNowByFileUuid(tusHookDto.getFileUuid());
|
tryMoveNowByFileUuid(tusFileHookDto.getFileUuid());
|
||||||
} catch (NoSuchFileException e) {
|
} catch (NoSuchFileException e) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
@@ -336,14 +368,14 @@ public class TusFileService {
|
|||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
tryMoveNowByFileUuid(tusHookDto.getFileUuid()); // 1회 재시도
|
tryMoveNowByFileUuid(tusFileHookDto.getFileUuid()); // 1회 재시도
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
log.error("Move failed after retry. fileUuid={}", tusHookDto.getFileUuid(), ex);
|
log.error("Move failed after retry. fileUuid={}", tusFileHookDto.getFileUuid(), ex);
|
||||||
markMovePending(tusHookDto.getFileUuid(), truncateErr(ex.toString()));
|
markMovePending(tusFileHookDto.getFileUuid(), truncateErr(ex.toString()));
|
||||||
}
|
}
|
||||||
} catch (Exception moveEx) {
|
} catch (Exception moveEx) {
|
||||||
log.error("Move failed. fileUuid={}", tusHookDto.getFileUuid(), moveEx);
|
log.error("Move failed. fileUuid={}", tusFileHookDto.getFileUuid(), moveEx);
|
||||||
markMovePending(tusHookDto.getFileUuid(), truncateErr(moveEx.toString()));
|
markMovePending(tusFileHookDto.getFileUuid(), truncateErr(moveEx.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +384,7 @@ public class TusFileService {
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void tryMoveNowByFileUuid(String fileUuid) throws IOException {
|
public void tryMoveNowByFileUuid(String fileUuid) throws IOException {
|
||||||
FileMoveTaskDto task = tusFileMapper.selectMoveTaskByFileUuid(fileUuid);
|
TusFileMoveTaskDto task = tusFileMapper.selectTusFileMoveTask(fileUuid);
|
||||||
if (task == null) return;
|
if (task == null) return;
|
||||||
if (task.getMoveYn() != null && !"N".equalsIgnoreCase(task.getMoveYn())) return;
|
if (task.getMoveYn() != null && !"N".equalsIgnoreCase(task.getMoveYn())) return;
|
||||||
|
|
||||||
@@ -373,15 +405,15 @@ public class TusFileService {
|
|||||||
task.setSavePath(toSavePath(finalPath));
|
task.setSavePath(toSavePath(finalPath));
|
||||||
task.setSaveName(finalPath.getFileName().toString());
|
task.setSaveName(finalPath.getFileName().toString());
|
||||||
task.setExt(extractExt(task.getSaveName()));
|
task.setExt(extractExt(task.getSaveName()));
|
||||||
tusFileMapper.updateFileMoveSuccess(task);
|
tusFileMapper.updateTusFileMoveSuccess(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void markMovePending(String fileUuid, String errMsg) {
|
public void markMovePending(String fileUuid, String errMsg) {
|
||||||
FileMoveTaskDto task = new FileMoveTaskDto();
|
TusFileMoveTaskDto tusFileMoveTaskDto = new TusFileMoveTaskDto();
|
||||||
task.setFileUuid(fileUuid);
|
tusFileMoveTaskDto.setFileUuid(fileUuid);
|
||||||
task.setMoveLastError(errMsg == null ? "move failed" : errMsg);
|
tusFileMoveTaskDto.setMoveLastError(errMsg == null ? "move failed" : errMsg);
|
||||||
tusFileMapper.updateFileMovePendingByFileUuid(task); // MOVE_YN='N', TRY_COUNT+1, LAST_ERROR
|
tusFileMapper.updateTusFileMovePending(tusFileMoveTaskDto); // MOVE_YN='N', TRY_COUNT+1, LAST_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
private String truncateErr(String s) {
|
private String truncateErr(String s) {
|
||||||
@@ -389,7 +421,7 @@ public class TusFileService {
|
|||||||
return s.length() > 500 ? s.substring(0, 500) : s;
|
return s.length() > 500 ? s.substring(0, 500) : s;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Path resolveTmpPath(FileMoveTaskDto task) {
|
private Path resolveTmpPath(TusFileMoveTaskDto task) {
|
||||||
// 예: /srv/project/alist/uploads/tmp/{tusUploadId}
|
// 예: /srv/project/alist/uploads/tmp/{tusUploadId}
|
||||||
if (task.getTusUploadId() == null || task.getTusUploadId().isBlank()) {
|
if (task.getTusUploadId() == null || task.getTusUploadId().isBlank()) {
|
||||||
throw new IllegalStateException("tusUploadId is empty");
|
throw new IllegalStateException("tusUploadId is empty");
|
||||||
@@ -397,7 +429,7 @@ public class TusFileService {
|
|||||||
return Paths.get(uploadTmpRoot, task.getTusUploadId());
|
return Paths.get(uploadTmpRoot, task.getTusUploadId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Path buildFinalPath(FileMoveTaskDto task) {
|
private Path buildFinalPath(TusFileMoveTaskDto task) {
|
||||||
String ext = extractExt(task.getOriginName());
|
String ext = extractExt(task.getOriginName());
|
||||||
String fileName = (task.getFileUuid() == null ? UUID.randomUUID().toString() : task.getFileUuid())
|
String fileName = (task.getFileUuid() == null ? UUID.randomUUID().toString() : task.getFileUuid())
|
||||||
+ (ext.isBlank() ? "" : "." + ext);
|
+ (ext.isBlank() ? "" : "." + ext);
|
||||||
@@ -449,15 +481,15 @@ public class TusFileService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*레이디스에 상태값 저장*/
|
/*레이디스에 상태값 저장*/
|
||||||
public void saveUploadStatusRedisTusHook(TusHookDto tusHookDto) {
|
public void saveTusFileHookStatusRedis(TusFileHookDto tusFileHookDto) {
|
||||||
if (tusHookDto == null || tusHookDto.getFileUuid() == null || tusHookDto.getFileUuid().isBlank()) {
|
if (tusFileHookDto == null || tusFileHookDto.getFileUuid() == null || tusFileHookDto.getFileUuid().isBlank()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = buildUploadStatusKey(tusHookDto.getFileUuid().trim());
|
String key = buildUploadStatusKey(tusFileHookDto.getFileUuid().trim());
|
||||||
String type = tusHookDto.getType() == null ? "" : tusHookDto.getType().trim().toLowerCase();
|
String type = tusFileHookDto.getType() == null ? "" : tusFileHookDto.getType().trim().toLowerCase();
|
||||||
long total = tusHookDto.getSize() == null ? 0L : tusHookDto.getSize();
|
long total = tusFileHookDto.getSize() == null ? 0L : tusFileHookDto.getSize();
|
||||||
long uploaded = tusHookDto.getOffset() == null ? 0L : tusHookDto.getOffset();
|
long uploaded = tusFileHookDto.getOffset() == null ? 0L : tusFileHookDto.getOffset();
|
||||||
|
|
||||||
String status = "UPLOADING";
|
String status = "UPLOADING";
|
||||||
if ("post-finish".equals(type)) {
|
if ("post-finish".equals(type)) {
|
||||||
@@ -472,7 +504,7 @@ public class TusFileService {
|
|||||||
int percent = (total > 0) ? (int) Math.min(100, (uploaded * 100) / total) : 0;
|
int percent = (total > 0) ? (int) Math.min(100, (uploaded * 100) / total) : 0;
|
||||||
|
|
||||||
HashOperations<String, Object, Object> ops = stringRedisTemplate.opsForHash();
|
HashOperations<String, Object, Object> ops = stringRedisTemplate.opsForHash();
|
||||||
ops.put(key, "fileUuid", tusHookDto.getFileUuid());
|
ops.put(key, "fileUuid", tusFileHookDto.getFileUuid());
|
||||||
ops.put(key, "status", status);
|
ops.put(key, "status", status);
|
||||||
ops.put(key, "uploadedBytes", String.valueOf(uploaded));
|
ops.put(key, "uploadedBytes", String.valueOf(uploaded));
|
||||||
ops.put(key, "totalBytes", String.valueOf(total));
|
ops.put(key, "totalBytes", String.valueOf(total));
|
||||||
@@ -510,14 +542,14 @@ public class TusFileService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildAuthCacheKey(UploadTokenDto dto) {
|
private String buildAuthCacheKey(TusFileUploadAuthDto tusFileUploadAuthDto) {
|
||||||
String normalizedName = normalize(dto.getOriginName());
|
String normalizedName = normalize(tusFileUploadAuthDto.getOriginName());
|
||||||
String normalizedType = normalize(dto.getContentType());
|
String normalizedType = normalize(tusFileUploadAuthDto.getContentType());
|
||||||
String normalizedSize = (dto.getSizeBytes() == null) ? "" : String.valueOf(dto.getSizeBytes());
|
String normalizedSize = (tusFileUploadAuthDto.getSizeBytes() == null) ? "" : String.valueOf(tusFileUploadAuthDto.getSizeBytes());
|
||||||
|
|
||||||
String raw = String.join("|",
|
String raw = String.join("|",
|
||||||
normalize(dto.getFileUuid()),
|
normalize(tusFileUploadAuthDto.getFileUuid()),
|
||||||
dto.getUploadToken() == null ? "" : dto.getUploadToken(),
|
tusFileUploadAuthDto.getUploadToken() == null ? "" : tusFileUploadAuthDto.getUploadToken(),
|
||||||
normalizedName,
|
normalizedName,
|
||||||
normalizedType,
|
normalizedType,
|
||||||
normalizedSize
|
normalizedSize
|
||||||
@@ -545,96 +577,117 @@ public class TusFileService {
|
|||||||
return (uploadAuthCacheTtlSeconds > 0) ? uploadAuthCacheTtlSeconds : 20L;
|
return (uploadAuthCacheTtlSeconds > 0) ? uploadAuthCacheTtlSeconds : 20L;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMetadataMismatch(FileUploadMetaDto fileUploadMetaDto, TusHookDto tusHookDto) {
|
private boolean isMetadataMismatch(TusFileUploadMetaDto tusFileUploadMetaDto, TusFileHookDto tusFileHookDto) {
|
||||||
if (tusHookDto.getSize() != null && fileUploadMetaDto.getSizeBytes() != null && !tusHookDto.getSize().equals(fileUploadMetaDto.getSizeBytes())) {
|
if (tusFileHookDto.getSize() != null && tusFileUploadMetaDto.getSizeBytes() != null && !tusFileHookDto.getSize().equals(tusFileUploadMetaDto.getSizeBytes())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (tusHookDto.getFilename() != null && !tusHookDto.getFilename().isBlank()
|
if (tusFileHookDto.getFilename() != null && !tusFileHookDto.getFilename().isBlank()
|
||||||
&& fileUploadMetaDto.getOriginName() != null && !fileUploadMetaDto.getOriginName().equals(tusHookDto.getFilename())) {
|
&& tusFileUploadMetaDto.getOriginName() != null && !tusFileUploadMetaDto.getOriginName().equals(tusFileHookDto.getFilename())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (tusHookDto.getFiletype() != null && !tusHookDto.getFiletype().isBlank()
|
if (tusFileHookDto.getFiletype() != null && !tusFileHookDto.getFiletype().isBlank()
|
||||||
&& fileUploadMetaDto.getContentType() != null && !fileUploadMetaDto.getContentType().isBlank()
|
&& tusFileUploadMetaDto.getContentType() != null && !tusFileUploadMetaDto.getContentType().isBlank()
|
||||||
&& !fileUploadMetaDto.getContentType().equalsIgnoreCase(tusHookDto.getFiletype())) {
|
&& !tusFileUploadMetaDto.getContentType().equalsIgnoreCase(tusFileHookDto.getFiletype())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public boolean updateUploadCancel(UploadCancelDto uploadCancelDto) {
|
public TusFileUploadCancelVo updateTusFileUploadCancel(TusFileUploadCancelDto tusFileUploadCancelDto) {
|
||||||
if (uploadCancelDto.getFileUuid() == null || uploadCancelDto.getFileUuid().isBlank() || uploadCancelDto.getUserTokenIdx() == null) {
|
TusFileUploadCancelVo tusFileUploadCancelVo = new TusFileUploadCancelVo();
|
||||||
return false;
|
|
||||||
|
if (tusFileUploadCancelDto.getFileUuid() == null
|
||||||
|
|| tusFileUploadCancelDto.getFileUuid().isBlank()
|
||||||
|
|| tusFileUploadCancelDto.getUserTokenIdx() == null) {
|
||||||
|
tusFileUploadCancelVo.setCanceled(false);
|
||||||
|
tusFileUploadCancelVo.setResultCode(4003);
|
||||||
|
return tusFileUploadCancelVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
int allowed = tusFileMapper.selectFileDetailCountByFileUuidAndUserToKenIdx(uploadCancelDto);
|
int tusFileUploadCancelCount = tusFileMapper.selectTusFileUploadCancelCount(tusFileUploadCancelDto);
|
||||||
if (allowed <= 0) {
|
if (tusFileUploadCancelCount <= 0) {
|
||||||
return false;
|
tusFileUploadCancelVo.setCanceled(false);
|
||||||
|
tusFileUploadCancelVo.setResultCode(2003);
|
||||||
|
return tusFileUploadCancelVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
UploadCancelDto progress = tusFileMapper.selectUploadProgressByFileUuid(uploadCancelDto);
|
TusFileUploadCancelProgressVo tusFileUploadCancelProgressVo = tusFileMapper.selectTusFileUploadCancelProgress(tusFileUploadCancelDto);
|
||||||
long uploaded = (progress != null && progress.getUploadedBytes() != null) ? progress.getUploadedBytes() : 0L;
|
|
||||||
long total = (progress != null && progress.getSizeBytes() != null) ? progress.getSizeBytes() : 0L;
|
|
||||||
|
|
||||||
int updated = tusFileMapper.updateFileDetailCanceledByFileUuidAndUserTokenIdx(uploadCancelDto);
|
long uploadedBytes = (tusFileUploadCancelProgressVo != null && tusFileUploadCancelProgressVo.getUploadedBytes() != null)
|
||||||
if (updated <= 0) {
|
? tusFileUploadCancelProgressVo.getUploadedBytes()
|
||||||
return false;
|
: 0L;
|
||||||
|
|
||||||
|
long totalBytes = (tusFileUploadCancelProgressVo != null && tusFileUploadCancelProgressVo.getSizeBytes() != null)
|
||||||
|
? tusFileUploadCancelProgressVo.getSizeBytes()
|
||||||
|
: 0L;
|
||||||
|
|
||||||
|
int updateCount = tusFileMapper.updateTusFileUploadCancel(tusFileUploadCancelDto);
|
||||||
|
if (updateCount <= 0) {
|
||||||
|
tusFileUploadCancelVo.setCanceled(false);
|
||||||
|
tusFileUploadCancelVo.setResultCode(2003);
|
||||||
|
return tusFileUploadCancelVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
tusFileMapper.updateFileMasterAggregateByFileUuid(uploadCancelDto.getFileUuid());
|
tusFileMapper.updateFileMasterAggregateByFileUuid(tusFileUploadCancelDto.getFileUuid());
|
||||||
saveCanceledStatusRedis(uploadCancelDto.getFileUuid(), uploaded, total); // 필요하면 기존 bytes 조회해서 넣어도 됨
|
saveCanceledStatusRedis(tusFileUploadCancelDto.getFileUuid(), uploadedBytes, totalBytes);
|
||||||
return true;
|
|
||||||
|
tusFileUploadCancelVo.setCanceled(true);
|
||||||
|
tusFileUploadCancelVo.setResultCode(200);
|
||||||
|
return tusFileUploadCancelVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public FileDownloadListDto selectFileDownloadListByFileMasterIdx(FileDownloadDto fileDownloadDto) {
|
public TusFileListVo selectTusFileList(TusFileListDto tusFileListDto) {
|
||||||
FileDownloadListDto fileDownloadList = new FileDownloadListDto();
|
TusFileListVo tusFileListVo = new TusFileListVo();
|
||||||
|
|
||||||
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
||||||
if (userTokenIdx == null) {
|
if (userTokenIdx == null) {
|
||||||
fileDownloadList.setResultCode(401);
|
tusFileListVo.setResultCode(401);
|
||||||
return fileDownloadList;
|
return tusFileListVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileDownloadDto.setUserTokenIdx(userTokenIdx);
|
tusFileListDto.setUserTokenIdx(userTokenIdx);
|
||||||
|
|
||||||
fileDownloadList.setFileMasterIdx(fileDownloadDto.getFileMasterIdx());
|
tusFileListVo.setFileMasterIdx(tusFileListDto.getFileMasterIdx());
|
||||||
|
|
||||||
List<FileDownloadItemDto> itemList = tusFileMapper.selectFileDownloadListByFileMasterIdx(fileDownloadDto);
|
List<TusFileListItemVo> tusFileList = tusFileMapper.selectTusFileList(tusFileListDto);
|
||||||
|
|
||||||
for (FileDownloadItemDto item : itemList) {
|
for (TusFileListItemVo item : tusFileList) {
|
||||||
item.setViewUrl("/tus/file/view/" + item.getFileUuid());
|
item.setViewUrl("/tus/file/view/" + item.getFileUuid());
|
||||||
item.setDownloadUrl("/tus/file/download/" + item.getFileUuid());
|
item.setDownloadUrl("/tus/file/download/" + item.getFileUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
fileDownloadList.setItemList(itemList);
|
tusFileListVo.setItemList(tusFileList);
|
||||||
fileDownloadList.setResultCode(200);
|
tusFileListVo.setResultCode(200);
|
||||||
|
|
||||||
return fileDownloadList;
|
return tusFileListVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileDownloadDto selectFileViewOrDownload(FileDownloadDto fileDownloadDto) {
|
@Transactional
|
||||||
|
public TusFileViewOrDownloadVo selectTusFileViewOrDownload(TusFileViewOrDownloadDto tusFileViewOrDownloadDto) {
|
||||||
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
||||||
if (userTokenIdx == null) {
|
if (userTokenIdx == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileDownloadDto.setUserTokenIdx(userTokenIdx);
|
tusFileViewOrDownloadDto.setUserTokenIdx(userTokenIdx);
|
||||||
|
|
||||||
FileDownloadDto fileDetailInfo = tusFileMapper.selectFileDetailByFileUuid(fileDownloadDto);
|
TusFileViewOrDownloadVo tusFileViewOrDownloadVo = tusFileMapper.selectTusFileViewOrDownload(tusFileViewOrDownloadDto);
|
||||||
|
|
||||||
if (fileDetailInfo == null) {
|
if (tusFileViewOrDownloadVo == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileDetailInfo.setUserTokenIdx(fileDownloadDto.getUserTokenIdx());
|
tusFileViewOrDownloadVo.setUserTokenIdx(tusFileViewOrDownloadDto.getUserTokenIdx());
|
||||||
fileDetailInfo.setEventType(fileDownloadDto.getEventType());
|
tusFileViewOrDownloadVo.setEventType(tusFileViewOrDownloadDto.getEventType());
|
||||||
fileDetailInfo.setClientIp(fileDownloadDto.getClientIp());
|
tusFileViewOrDownloadVo.setClientIp(tusFileViewOrDownloadDto.getClientIp());
|
||||||
fileDetailInfo.setUserAgent(fileDownloadDto.getUserAgent());
|
tusFileViewOrDownloadVo.setUserAgent(tusFileViewOrDownloadDto.getUserAgent());
|
||||||
fileDetailInfo.setReferer(fileDownloadDto.getReferer());
|
tusFileViewOrDownloadVo.setReferer(tusFileViewOrDownloadDto.getReferer());
|
||||||
|
|
||||||
tusFileMapper.insertFileDownloadEventLog(fileDetailInfo);
|
tusFileMapper.insertTusFileViewOrDownloadEventLog(tusFileViewOrDownloadVo);
|
||||||
return fileDetailInfo;
|
|
||||||
|
return tusFileViewOrDownloadVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Path resolveStoredFilePath(String savePath) {
|
public Path resolveStoredFilePath(String savePath) {
|
||||||
@@ -655,31 +708,46 @@ public class TusFileService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public boolean updateFileDelete(FileDeleteDto fileDeleteDto) {
|
public TusFileDeleteVo updateTusFileDelete(TusFileDeleteDto tusFileDeleteDto) {
|
||||||
if (fileDeleteDto == null || fileDeleteDto.getFileUuid() == null || fileDeleteDto.getFileUuid().isBlank()) {
|
TusFileDeleteVo tusFileDeleteVo = new TusFileDeleteVo();
|
||||||
return false;
|
|
||||||
|
if (tusFileDeleteDto == null
|
||||||
|
|| tusFileDeleteDto.getFileUuid() == null
|
||||||
|
|| tusFileDeleteDto.getFileUuid().isBlank()) {
|
||||||
|
tusFileDeleteVo.setDeleted(false);
|
||||||
|
tusFileDeleteVo.setResultCode(4003);
|
||||||
|
return tusFileDeleteVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx();
|
||||||
if (userTokenIdx == null) {
|
if (userTokenIdx == null) {
|
||||||
return false;
|
tusFileDeleteVo.setDeleted(false);
|
||||||
|
tusFileDeleteVo.setResultCode(401);
|
||||||
|
return tusFileDeleteVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileDeleteDto.setUserTokenIdx(userTokenIdx);
|
tusFileDeleteDto.setUserTokenIdx(userTokenIdx);
|
||||||
fileDeleteDto.setFileUuid(fileDeleteDto.getFileUuid().trim());
|
tusFileDeleteDto.setFileUuid(tusFileDeleteDto.getFileUuid().trim());
|
||||||
|
|
||||||
int allowed = tusFileMapper.selectFileDeleteTargetCount(fileDeleteDto);
|
int tusFileDeleteTargetCount = tusFileMapper.selectTusFileDeleteTargetCount(tusFileDeleteDto);
|
||||||
if (allowed <= 0) {
|
if (tusFileDeleteTargetCount <= 0) {
|
||||||
return false;
|
tusFileDeleteVo.setDeleted(false);
|
||||||
|
tusFileDeleteVo.setResultCode(2003);
|
||||||
|
return tusFileDeleteVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
int detailUpdated = tusFileMapper.updateFileDetailDeleteByFileUuid(fileDeleteDto);
|
int tusFileDetailDeleteCount = tusFileMapper.updateTusFileDetailDelete(tusFileDeleteDto);
|
||||||
if (detailUpdated <= 0) {
|
if (tusFileDetailDeleteCount <= 0) {
|
||||||
return false;
|
tusFileDeleteVo.setDeleted(false);
|
||||||
|
tusFileDeleteVo.setResultCode(2003);
|
||||||
|
return tusFileDeleteVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
tusFileMapper.updateFileMasterDeleteByFileUuid(fileDeleteDto);
|
tusFileMapper.updateTusFileMasterDelete(tusFileDeleteDto);
|
||||||
return true;
|
|
||||||
|
tusFileDeleteVo.setDeleted(true);
|
||||||
|
tusFileDeleteVo.setResultCode(200);
|
||||||
|
return tusFileDeleteVo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 파일 삭제 응답")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileDeleteVo {
|
||||||
|
@Schema(description = "파일 삭제 처리 여부", example = "true")
|
||||||
|
private boolean deleted;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private Integer resultCode;
|
||||||
|
}
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
package com.alist.api.modules.tusFile.dto;
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -7,7 +7,7 @@ import lombok.Setter;
|
|||||||
@Schema(description = "다운로드 파일 항목")
|
@Schema(description = "다운로드 파일 항목")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class FileDownloadItemDto {
|
public class TusFileListItemVo {
|
||||||
@Schema(description = "파일 상세 PK", example = "1")
|
@Schema(description = "파일 상세 PK", example = "1")
|
||||||
private Long fileDetailIdx;
|
private Long fileDetailIdx;
|
||||||
|
|
||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
package com.alist.api.modules.tusFile.dto;
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
@@ -10,12 +10,12 @@ import java.util.List;
|
|||||||
@Schema(description = "파일 다운로드 목록 응답")
|
@Schema(description = "파일 다운로드 목록 응답")
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class FileDownloadListDto {
|
public class TusFileListVo {
|
||||||
@Schema(description = "파일 마스터 PK", example = "1")
|
@Schema(description = "파일 마스터 PK", example = "1")
|
||||||
private Long fileMasterIdx;
|
private Long fileMasterIdx;
|
||||||
|
|
||||||
@Schema(description = "다운로드 파일 목록")
|
@Schema(description = "다운로드 파일 목록")
|
||||||
private List<FileDownloadItemDto> itemList;
|
private List<TusFileListItemVo> itemList;
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
@Schema(hidden = true)
|
@Schema(hidden = true)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 업로드 권한 검증 응답")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileUploadAuthVo {
|
||||||
|
@JsonIgnore
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private Integer resultCode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileUploadCancelProgressVo {
|
||||||
|
private String fileUuid;
|
||||||
|
private Long uploadedBytes;
|
||||||
|
private Long sizeBytes;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 업로드 취소 응답")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileUploadCancelVo {
|
||||||
|
@JsonIgnore
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private boolean canceled;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private Integer resultCode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 파일 업로드 초기화 파일 항목 응답")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileUploadInitItemVo {
|
||||||
|
@Schema(description = "파일 순번", example = "1")
|
||||||
|
private Integer fileSeq;
|
||||||
|
|
||||||
|
@Schema(description = "파일 UUID", example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10")
|
||||||
|
private String fileUuid;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 업로드 토큰")
|
||||||
|
private String uploadToken;
|
||||||
|
|
||||||
|
@Schema(description = "원본 파일명", example = "sample.png")
|
||||||
|
private String originName;
|
||||||
|
|
||||||
|
@Schema(description = "파일 크기(byte)", example = "102400")
|
||||||
|
private Long sizeBytes;
|
||||||
|
|
||||||
|
@Schema(description = "Content-Type", example = "image/png")
|
||||||
|
private String contentType;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 파일 업로드 초기화 응답")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileUploadInitVo {
|
||||||
|
@Schema(description = "파일 마스터 PK", example = "1")
|
||||||
|
private Long fileMasterIdx;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 업로드 엔드포인트", example = "https://file-alist.pjt.kr/tus/file/")
|
||||||
|
private String tusEndpoint;
|
||||||
|
|
||||||
|
@Schema(description = "업로드 파일 항목 목록")
|
||||||
|
private List<TusFileUploadInitItemVo> itemList;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 업로드 상태 조회 응답")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileUploadStatusVo {
|
||||||
|
@Schema(description = "파일 UUID", example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10")
|
||||||
|
private String fileUuid;
|
||||||
|
|
||||||
|
@Schema(description = "업로드 상태. PENDING, UPLOADING, DONE, CANCELED", example = "UPLOADING")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Schema(description = "업로드 완료 byte", example = "51200")
|
||||||
|
private Long uploadedBytes;
|
||||||
|
|
||||||
|
@Schema(description = "전체 파일 크기 byte", example = "102400")
|
||||||
|
private Long totalBytes;
|
||||||
|
|
||||||
|
@Schema(description = "업로드 진행률", example = "50")
|
||||||
|
private Integer percent;
|
||||||
|
|
||||||
|
@Schema(description = "상태 갱신 시각", example = "2026-05-19T10:30:00")
|
||||||
|
private String updatedAt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.alist.api.modules.tusFile.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Schema(description = "TUS 파일 보기/다운로드 조회 결과")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class TusFileViewOrDownloadVo {
|
||||||
|
@Schema(description = "파일 상세 PK", example = "1")
|
||||||
|
private Long fileDetailIdx;
|
||||||
|
|
||||||
|
@Schema(description = "파일 마스터 PK", example = "1")
|
||||||
|
private Long fileMasterIdx;
|
||||||
|
|
||||||
|
@Schema(description = "파일 UUID", example = "018f6f2d-7b5c-7d49-9c3a-8c0f4f9f9f10")
|
||||||
|
private String fileUuid;
|
||||||
|
|
||||||
|
@Schema(description = "원본 파일명", example = "sample.png")
|
||||||
|
private String originName;
|
||||||
|
|
||||||
|
@Schema(description = "Content-Type", example = "image/png")
|
||||||
|
private String contentType;
|
||||||
|
|
||||||
|
@Schema(description = "파일 크기(byte)", example = "102400")
|
||||||
|
private Long sizeBytes;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String savePath;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private Integer userIdx;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private Integer userTokenIdx;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String eventType;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String clientIp;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String userAgent;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String referer;
|
||||||
|
}
|
||||||
@@ -2,9 +2,147 @@
|
|||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
<mapper namespace="com.alist.api.modules.tusFile.mapper.TusFileMapper">
|
<mapper namespace="com.alist.api.modules.tusFile.mapper.TusFileMapper">
|
||||||
|
<select id="selectTusFileUploadAuthCount" resultType="java.lang.Integer">
|
||||||
|
/*TusFileMapper.selectTusFileUploadAuthCount*/
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM ALISTLMS.FILE_DETAIL LFD
|
||||||
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFD.CREATE_MEMBER
|
||||||
|
WHERE LFD.DEL_YN = 'N'
|
||||||
|
AND LFD.FILE_UUID = #{fileUuid}
|
||||||
|
AND LTUT.user_token_idx = #{userTokenIdx}
|
||||||
|
AND LFD.STATUS IN (0,1,2,3)
|
||||||
|
AND (#{sizeBytes} IS NULL OR LFD.SIZE_BYTES = #{sizeBytes})
|
||||||
|
AND (#{originName} IS NULL OR #{originName} = '' OR LFD.ORIGIN_NAME = #{originName})
|
||||||
|
AND (
|
||||||
|
#{contentType} IS NULL OR #{contentType} = ''
|
||||||
|
OR LFD.CONTENT_TYPE IS NULL OR LFD.CONTENT_TYPE = ''
|
||||||
|
OR LOWER(LFD.CONTENT_TYPE) = LOWER(#{contentType})
|
||||||
|
)
|
||||||
|
</select>
|
||||||
|
|
||||||
<insert id="insertFileMasterInit" useGeneratedKeys="true" keyProperty="fileMasterIdx">
|
<select id="selectTusFileUploadMeta" resultType="com.alist.api.modules.tusFile.dto.TusFileUploadMetaDto">
|
||||||
/*FileMapper.insertFileMasterInit*/
|
/*TusFileMapper.selectTusFileUploadMeta*/
|
||||||
|
SELECT FILE_UUID, ORIGIN_NAME, SIZE_BYTES, CONTENT_TYPE, TUS_UPLOAD_ID, STATUS
|
||||||
|
FROM ALISTLMS.FILE_DETAIL
|
||||||
|
WHERE FILE_UUID = #{fileUuid}
|
||||||
|
AND DEL_YN = 'N'
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectTusFileUploadCancelCount" resultType="java.lang.Integer">
|
||||||
|
/*TusFileMapper.selectTusFileUploadCancelCount*/
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM ALISTLMS.FILE_DETAIL LFD
|
||||||
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFD.CREATE_MEMBER
|
||||||
|
WHERE LFD.DEL_YN = 'N'
|
||||||
|
AND LFD.FILE_UUID = #{fileUuid}
|
||||||
|
AND LTUT.user_token_idx = #{userTokenIdx}
|
||||||
|
AND LFD.STATUS IN (0,1,2)
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectTusFileUploadCancelProgress" resultType="com.alist.api.modules.tusFile.vo.TusFileUploadCancelProgressVo">
|
||||||
|
/*TusFileMapper.selectTusFileUploadCancelProgress*/
|
||||||
|
SELECT LFD.FILE_UUID
|
||||||
|
, COALESCE(LFD.UPLOADED_BYTES, 0) AS UPLOADED_BYTES
|
||||||
|
, COALESCE(LFD.SIZE_BYTES, 0) AS SIZE_BYTES
|
||||||
|
FROM ALISTLMS.FILE_DETAIL LFD
|
||||||
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFD.CREATE_MEMBER
|
||||||
|
WHERE LFD.FILE_UUID = #{fileUuid}
|
||||||
|
AND LTUT.user_token_idx = #{userTokenIdx}
|
||||||
|
AND LFD.DEL_YN = 'N'
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectTusFileMoveTask" resultType="com.alist.api.modules.tusFile.dto.TusFileMoveTaskDto">
|
||||||
|
/*TusFileMapper.selectTusFileMoveTask*/
|
||||||
|
SELECT LFD.FILE_DETAIL_IDX
|
||||||
|
, LFD.FILE_MASTER_IDX
|
||||||
|
, LFD.FILE_UUID
|
||||||
|
, LFD.TUS_UPLOAD_ID
|
||||||
|
, LFD.ORIGIN_NAME
|
||||||
|
, LFD.CONTENT_TYPE
|
||||||
|
, LFD.SIZE_BYTES
|
||||||
|
, LFD.UPLOADED_BYTES
|
||||||
|
, LFM.FOLDER_PATH
|
||||||
|
, LFD.SAVE_NAME
|
||||||
|
, LFD.SAVE_PATH
|
||||||
|
, LFD.`EXT`
|
||||||
|
, LFD.MOVE_YN
|
||||||
|
, LFD.MOVE_TRY_COUNT
|
||||||
|
, LFD.MOVE_LAST_ERROR
|
||||||
|
FROM ALISTLMS.FILE_DETAIL LFD
|
||||||
|
INNER JOIN ALISTLMS.FILE_MASTER LFM ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
||||||
|
AND LFM.DEL_YN = 'N'
|
||||||
|
WHERE LFD.FILE_UUID = #{fileUuid}
|
||||||
|
AND LFD.DEL_YN = 'N'
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectTusFileList" resultType="com.alist.api.modules.tusFile.vo.TusFileListItemVo">
|
||||||
|
/*TusFileMapper.selectTusFileList*/
|
||||||
|
SELECT LFD.FILE_DETAIL_IDX
|
||||||
|
, LFD.FILE_MASTER_IDX
|
||||||
|
, LFD.FILE_UUID
|
||||||
|
, LFD.ORIGIN_NAME
|
||||||
|
, LFD.CONTENT_TYPE
|
||||||
|
, LFD.SIZE_BYTES
|
||||||
|
FROM ALISTLMS.FILE_DETAIL LFD
|
||||||
|
INNER JOIN ALISTLMS.FILE_MASTER LFM ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
||||||
|
AND LFM.DEL_YN = 'N'
|
||||||
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFM.USER_IDX
|
||||||
|
WHERE LFD.FILE_MASTER_IDX = #{fileMasterIdx}
|
||||||
|
AND LTUT.user_token_idx = #{userTokenIdx}
|
||||||
|
AND LFD.DEL_YN = 'N'
|
||||||
|
AND LFD.STATUS = 3
|
||||||
|
AND LFD.MOVE_YN = 'Y'
|
||||||
|
ORDER BY LFD.FILE_SEQ ASC, LFD.FILE_DETAIL_IDX ASC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectTusFileViewOrDownload" resultType="com.alist.api.modules.tusFile.vo.TusFileViewOrDownloadVo">
|
||||||
|
/*TusFileMapper.selectTusFileViewOrDownload*/
|
||||||
|
SELECT LFD.FILE_DETAIL_IDX
|
||||||
|
, LFD.FILE_MASTER_IDX
|
||||||
|
, LFD.FILE_UUID
|
||||||
|
, LFD.ORIGIN_NAME
|
||||||
|
, LFD.CONTENT_TYPE
|
||||||
|
, LFD.SIZE_BYTES
|
||||||
|
, LFD.SAVE_PATH
|
||||||
|
, LTUT.user_idx
|
||||||
|
FROM ALISTLMS.FILE_DETAIL LFD
|
||||||
|
INNER JOIN ALISTLMS.FILE_MASTER LFM ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
||||||
|
AND LFM.DEL_YN = 'N'
|
||||||
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFM.USER_IDX
|
||||||
|
WHERE LFD.FILE_UUID = #{fileUuid}
|
||||||
|
AND LTUT.user_token_idx = #{userTokenIdx}
|
||||||
|
AND LFD.DEL_YN = 'N'
|
||||||
|
AND LFD.STATUS = 3
|
||||||
|
AND LFD.MOVE_YN = 'Y'
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectTusFileDeleteTargetCount" resultType="java.lang.Integer">
|
||||||
|
/*TusFileMapper.selectTusFileDeleteTargetCount*/
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM ALISTLMS.FILE_DETAIL LFD
|
||||||
|
INNER JOIN ALISTLMS.FILE_MASTER LFM ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
||||||
|
AND LFM.DEL_YN = 'N'
|
||||||
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFM.USER_IDX
|
||||||
|
WHERE LFD.FILE_UUID = #{fileUuid}
|
||||||
|
AND LTUT.user_token_idx = #{userTokenIdx}
|
||||||
|
AND LFD.DEL_YN = 'N'
|
||||||
|
AND LFD.STATUS = 3
|
||||||
|
AND LFM.STATUS = 3
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectUserIdxByUserTokenIdx" resultType="java.lang.Integer">
|
||||||
|
/*TusFileMapper.selectUserIdxByUserTokenIdx*/
|
||||||
|
SELECT user_idx
|
||||||
|
FROM test_user_token
|
||||||
|
WHERE user_token_idx = #{userTokenIdx}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertTusFileUploadInitMaster" useGeneratedKeys="true" keyProperty="fileMasterIdx">
|
||||||
|
/*TusFileMapper.insertTusFileUploadInitMaster*/
|
||||||
INSERT INTO ALISTLMS.FILE_MASTER (
|
INSERT INTO ALISTLMS.FILE_MASTER (
|
||||||
USER_IDX, FILE_CATEGORY, FOLDER_PATH, TOTAL_COUNT, DONE_COUNT, FAIL_COUNT, STATUS, DEL_YN, CREATE_MEMBER, UPDATE_MEMBER
|
USER_IDX, FILE_CATEGORY, FOLDER_PATH, TOTAL_COUNT, DONE_COUNT, FAIL_COUNT, STATUS, DEL_YN, CREATE_MEMBER, UPDATE_MEMBER
|
||||||
) VALUES (
|
) VALUES (
|
||||||
@@ -12,8 +150,8 @@
|
|||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<insert id="insertFileDetailInit">
|
<insert id="insertTusFileUploadInitDetail">
|
||||||
/*FileMapper.insertFileDetailInit*/
|
/*TusFileMapper.insertTusFileUploadInitDetail*/
|
||||||
INSERT INTO ALISTLMS.FILE_DETAIL (
|
INSERT INTO ALISTLMS.FILE_DETAIL (
|
||||||
FILE_MASTER_IDX, FILE_SEQ, FILE_UUID, ORIGIN_NAME, CONTENT_TYPE, SIZE_BYTES, UPLOADED_BYTES, TUS_UPLOAD_ID, STATUS, DEL_YN, CREATE_MEMBER, UPDATE_MEMBER
|
FILE_MASTER_IDX, FILE_SEQ, FILE_UUID, ORIGIN_NAME, CONTENT_TYPE, SIZE_BYTES, UPLOADED_BYTES, TUS_UPLOAD_ID, STATUS, DEL_YN, CREATE_MEMBER, UPDATE_MEMBER
|
||||||
) VALUES (
|
) VALUES (
|
||||||
@@ -21,13 +159,12 @@
|
|||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<insert id="insertFileUploadEventLog">
|
<insert id="insertTusFileHookEventLog">
|
||||||
/*FileMapper.insertFileUploadEventLog*/
|
/*TusFileMapper.insertTusFileHookEventLog*/
|
||||||
INSERT INTO ALISTLMS.FILE_UPLOAD_EVENT_LOG (
|
INSERT INTO ALISTLMS.FILE_UPLOAD_EVENT_LOG (
|
||||||
FILE_DETAIL_IDX, EVENT_TYPE, OFFSET_BYTES, BYTES_WRITTEN, HTTP_STATUS, MESSAGE, RAW_JSON
|
FILE_DETAIL_IDX, EVENT_TYPE, OFFSET_BYTES, BYTES_WRITTEN, HTTP_STATUS, MESSAGE, RAW_JSON
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT LFD.FILE_DETAIL_IDX
|
||||||
LFD.FILE_DETAIL_IDX
|
|
||||||
, #{type}
|
, #{type}
|
||||||
, #{offset}
|
, #{offset}
|
||||||
, NULL
|
, NULL
|
||||||
@@ -38,8 +175,9 @@
|
|||||||
WHERE LFD.FILE_UUID = #{fileUuid}
|
WHERE LFD.FILE_UUID = #{fileUuid}
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
</insert>
|
</insert>
|
||||||
<insert id="insertFileDownloadEventLog">
|
|
||||||
/*FileMapper.insertFileDownloadEventLog*/
|
<insert id="insertTusFileViewOrDownloadEventLog">
|
||||||
|
/*TusFileMapper.insertTusFileViewOrDownloadEventLog*/
|
||||||
INSERT INTO ALISTLMS.FILE_DOWNLOAD_EVENT_LOG (
|
INSERT INTO ALISTLMS.FILE_DOWNLOAD_EVENT_LOG (
|
||||||
FILE_MASTER_IDX
|
FILE_MASTER_IDX
|
||||||
, FILE_DETAIL_IDX
|
, FILE_DETAIL_IDX
|
||||||
@@ -67,8 +205,8 @@
|
|||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<update id="updateFileDetailStatus">
|
<update id="updateTusFileHookDetailStatus">
|
||||||
/*FileMapper.updateFileDetailStatus*/
|
/*TusFileMapper.updateTusFileHookDetailStatus*/
|
||||||
UPDATE ALISTLMS.FILE_DETAIL
|
UPDATE ALISTLMS.FILE_DETAIL
|
||||||
<set>
|
<set>
|
||||||
<if test="uploadId != null and uploadId != ''">
|
<if test="uploadId != null and uploadId != ''">
|
||||||
@@ -87,14 +225,13 @@
|
|||||||
</update>
|
</update>
|
||||||
|
|
||||||
<update id="updateFileMasterAggregateByFileUuid">
|
<update id="updateFileMasterAggregateByFileUuid">
|
||||||
/*FileMapper.updateFileMasterAggregateByFileUuid*/
|
/*TusFileMapper.updateFileMasterAggregateByFileUuid*/
|
||||||
UPDATE ALISTLMS.FILE_MASTER LFM
|
UPDATE ALISTLMS.FILE_MASTER LFM
|
||||||
JOIN (
|
JOIN (
|
||||||
SELECT
|
SELECT LLFD.FILE_MASTER_IDX
|
||||||
LLFD.FILE_MASTER_IDX,
|
, COUNT(*) AS total_count
|
||||||
COUNT(*) AS total_count,
|
, SUM(CASE WHEN LLFD.STATUS = 3 THEN 1 ELSE 0 END) AS done_count
|
||||||
SUM(CASE WHEN LLFD.STATUS = 3 THEN 1 ELSE 0 END) AS done_count,
|
, SUM(CASE WHEN LLFD.STATUS IN (4,5) THEN 1 ELSE 0 END) AS fail_count
|
||||||
SUM(CASE WHEN LLFD.STATUS IN (4,5) THEN 1 ELSE 0 END) AS fail_count
|
|
||||||
FROM ALISTLMS.FILE_DETAIL LLFD
|
FROM ALISTLMS.FILE_DETAIL LLFD
|
||||||
WHERE LLFD.FILE_MASTER_IDX = (
|
WHERE LLFD.FILE_MASTER_IDX = (
|
||||||
SELECT FILE_MASTER_IDX
|
SELECT FILE_MASTER_IDX
|
||||||
@@ -115,8 +252,9 @@
|
|||||||
END
|
END
|
||||||
, LFM.UPDATE_DATE = NOW()
|
, LFM.UPDATE_DATE = NOW()
|
||||||
</update>
|
</update>
|
||||||
<update id="updateTusUploadIdIfNull" parameterType="com.alist.api.modules.tusFile.dto.FileUploadMetaDto">
|
|
||||||
/*FileMapper.updateTusUploadIdIfNull*/
|
<update id="updateTusFileUploadIdIfNull" parameterType="com.alist.api.modules.tusFile.dto.TusFileUploadMetaDto">
|
||||||
|
/*TusFileMapper.updateTusFileUploadIdIfNull*/
|
||||||
UPDATE ALISTLMS.FILE_DETAIL
|
UPDATE ALISTLMS.FILE_DETAIL
|
||||||
SET TUS_UPLOAD_ID = #{tusUploadId}
|
SET TUS_UPLOAD_ID = #{tusUploadId}
|
||||||
, UPDATE_DATE = NOW()
|
, UPDATE_DATE = NOW()
|
||||||
@@ -124,8 +262,9 @@
|
|||||||
AND DEL_YN = 'N'
|
AND DEL_YN = 'N'
|
||||||
AND TUS_UPLOAD_ID IS NULL
|
AND TUS_UPLOAD_ID IS NULL
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<update id="updateFileDetailCanceledByFileUuid">
|
<update id="updateFileDetailCanceledByFileUuid">
|
||||||
/*FileMapper.updateFileDetailCanceledByFileUuid*/
|
/*TusFileMapper.updateFileDetailCanceledByFileUuid*/
|
||||||
UPDATE ALISTLMS.FILE_DETAIL
|
UPDATE ALISTLMS.FILE_DETAIL
|
||||||
SET STATUS = 5
|
SET STATUS = 5
|
||||||
, UPDATE_DATE = NOW()
|
, UPDATE_DATE = NOW()
|
||||||
@@ -133,147 +272,9 @@
|
|||||||
AND DEL_YN = 'N'
|
AND DEL_YN = 'N'
|
||||||
AND STATUS IN (0,1,2)
|
AND STATUS IN (0,1,2)
|
||||||
</update>
|
</update>
|
||||||
<update id="updateFileDetailCanceledByFileUuidAndUserTokenIdx">
|
|
||||||
/*FileMapper.updateFileDetailCanceledByFileUuidAndUserTokenIdx*/
|
|
||||||
UPDATE ALISTLMS.FILE_DETAIL LFD
|
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
|
||||||
ON LTUT.user_idx = LFD.CREATE_MEMBER
|
|
||||||
SET LFD.STATUS = 5
|
|
||||||
, LFD.UPDATE_DATE = NOW()
|
|
||||||
WHERE LFD.DEL_YN = 'N'
|
|
||||||
AND LFD.FILE_UUID = #{fileUuid}
|
|
||||||
AND LTUT.user_token_idx = #{userTokenIdx}
|
|
||||||
AND LFD.STATUS IN (0,1,2)
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<select id="selectFileDetailCountByFileUuidUserToKenIdx" resultType="java.lang.Integer">
|
<update id="updateTusFileMoveSuccess" parameterType="com.alist.api.modules.tusFile.dto.TusFileMoveTaskDto">
|
||||||
/*FileMapper.selectFileDetailCountByFileUuidUserToKenIdx*/
|
/*TusFileMapper.updateTusFileMoveSuccess*/
|
||||||
SELECT COUNT(*)
|
|
||||||
FROM ALISTLMS.FILE_DETAIL LFD
|
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
|
||||||
ON LTUT.user_idx = LFD.CREATE_MEMBER
|
|
||||||
WHERE LFD.DEL_YN = 'N'
|
|
||||||
AND LFD.FILE_UUID = #{fileUuid}
|
|
||||||
AND LTUT.user_token_idx = #{userTokenIdx}
|
|
||||||
AND LFD.STATUS IN (0,1,2,3)
|
|
||||||
AND (#{sizeBytes} IS NULL OR LFD.SIZE_BYTES = #{sizeBytes})
|
|
||||||
AND (#{originName} IS NULL OR #{originName} = '' OR LFD.ORIGIN_NAME = #{originName})
|
|
||||||
AND (
|
|
||||||
#{contentType} IS NULL OR #{contentType} = ''
|
|
||||||
OR LFD.CONTENT_TYPE IS NULL OR LFD.CONTENT_TYPE = ''
|
|
||||||
OR LOWER(LFD.CONTENT_TYPE) = LOWER(#{contentType})
|
|
||||||
)
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectFileUploadMetaByFileUuid" resultType="com.alist.api.modules.tusFile.dto.FileUploadMetaDto">
|
|
||||||
/*FileMapper.selectFileUploadMetaByFileUuid*/
|
|
||||||
SELECT FILE_UUID, ORIGIN_NAME, SIZE_BYTES, CONTENT_TYPE, TUS_UPLOAD_ID, STATUS
|
|
||||||
FROM ALISTLMS.FILE_DETAIL
|
|
||||||
WHERE FILE_UUID = #{fileUuid}
|
|
||||||
AND DEL_YN = 'N'
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectFileDetailCountByFileUuidAndUserToKenIdx" resultType="java.lang.Integer">
|
|
||||||
/*FileMapper.selectFileDetailCountByFileUuidAndUserToKenIdx*/
|
|
||||||
SELECT COUNT(*)
|
|
||||||
FROM ALISTLMS.FILE_DETAIL LFD
|
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
|
||||||
ON LTUT.user_idx = LFD.CREATE_MEMBER
|
|
||||||
WHERE LFD.DEL_YN = 'N'
|
|
||||||
AND LFD.FILE_UUID = #{fileUuid}
|
|
||||||
AND LTUT.user_token_idx = #{userTokenIdx}
|
|
||||||
AND LFD.STATUS IN (0,1,2)
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectUploadProgressByFileUuid" resultType="com.alist.api.modules.tusFile.dto.UploadCancelDto">
|
|
||||||
/*FileMapper.selectUploadProgressByFileUuid*/
|
|
||||||
SELECT LFD.FILE_UUID
|
|
||||||
, COALESCE(LFD.UPLOADED_BYTES, 0) AS UPLOADED_BYTES
|
|
||||||
, COALESCE(LFD.SIZE_BYTES, 0) AS SIZE_BYTES
|
|
||||||
FROM ALISTLMS.FILE_DETAIL LFD
|
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
|
||||||
ON LTUT.user_idx = LFD.CREATE_MEMBER
|
|
||||||
WHERE LFD.FILE_UUID = #{fileUuid}
|
|
||||||
AND LTUT.user_token_idx = #{userTokenIdx}
|
|
||||||
AND LFD.DEL_YN = 'N'
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectMoveTaskByFileUuid" resultType="com.alist.api.modules.tusFile.dto.FileMoveTaskDto">
|
|
||||||
/*FileMapper.selectMoveTaskByFileUuid*/
|
|
||||||
SELECT LFD.FILE_DETAIL_IDX
|
|
||||||
, LFD.FILE_MASTER_IDX
|
|
||||||
, LFD.FILE_UUID
|
|
||||||
, LFD.TUS_UPLOAD_ID
|
|
||||||
, LFD.ORIGIN_NAME
|
|
||||||
, LFD.CONTENT_TYPE
|
|
||||||
, LFD.SIZE_BYTES
|
|
||||||
, LFD.UPLOADED_BYTES
|
|
||||||
, LFM.FOLDER_PATH
|
|
||||||
, LFD.SAVE_NAME
|
|
||||||
, LFD.SAVE_PATH
|
|
||||||
, LFD.`EXT`
|
|
||||||
, LFD.MOVE_YN
|
|
||||||
, LFD.MOVE_TRY_COUNT
|
|
||||||
, LFD.MOVE_LAST_ERROR
|
|
||||||
FROM ALISTLMS.FILE_DETAIL LFD
|
|
||||||
INNER JOIN ALISTLMS.FILE_MASTER LFM
|
|
||||||
ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
|
||||||
AND LFM.DEL_YN = 'N'
|
|
||||||
WHERE LFD.FILE_UUID = #{fileUuid}
|
|
||||||
AND LFD.DEL_YN = 'N'
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectFileDownloadListByFileMasterIdx" resultType="com.alist.api.modules.tusFile.dto.FileDownloadItemDto">
|
|
||||||
/*FileMapper.selectFileDownloadListByFileMasterIdx*/
|
|
||||||
SELECT LFD.FILE_DETAIL_IDX
|
|
||||||
, LFD.FILE_MASTER_IDX
|
|
||||||
, LFD.FILE_UUID
|
|
||||||
, LFD.ORIGIN_NAME
|
|
||||||
, LFD.CONTENT_TYPE
|
|
||||||
, LFD.SIZE_BYTES
|
|
||||||
FROM ALISTLMS.FILE_DETAIL LFD
|
|
||||||
INNER JOIN ALISTLMS.FILE_MASTER LFM
|
|
||||||
ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
|
||||||
AND LFM.DEL_YN = 'N'
|
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
|
||||||
ON LTUT.user_idx = LFM.USER_IDX
|
|
||||||
WHERE LFD.FILE_MASTER_IDX = #{fileMasterIdx}
|
|
||||||
AND LTUT.user_token_idx = #{userTokenIdx}
|
|
||||||
AND LFD.DEL_YN = 'N'
|
|
||||||
AND LFD.STATUS = 3
|
|
||||||
AND LFD.MOVE_YN = 'Y'
|
|
||||||
ORDER BY LFD.FILE_SEQ ASC, LFD.FILE_DETAIL_IDX ASC
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="selectFileDetailByFileUuid" resultType="com.alist.api.modules.tusFile.dto.FileDownloadDto">
|
|
||||||
/*FileMapper.selectFileDetailByFileUuid*/
|
|
||||||
SELECT LFD.FILE_DETAIL_IDX
|
|
||||||
, LFD.FILE_MASTER_IDX
|
|
||||||
, LFD.FILE_UUID
|
|
||||||
, LFD.ORIGIN_NAME
|
|
||||||
, LFD.CONTENT_TYPE
|
|
||||||
, LFD.SIZE_BYTES
|
|
||||||
, LFD.SAVE_PATH
|
|
||||||
, LTUT.user_idx
|
|
||||||
FROM ALISTLMS.FILE_DETAIL LFD
|
|
||||||
INNER JOIN ALISTLMS.FILE_MASTER LFM
|
|
||||||
ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
|
||||||
AND LFM.DEL_YN = 'N'
|
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
|
||||||
ON LTUT.user_idx = LFM.USER_IDX
|
|
||||||
WHERE LFD.FILE_UUID = #{fileUuid}
|
|
||||||
AND LTUT.user_token_idx = #{userTokenIdx}
|
|
||||||
AND LFD.DEL_YN = 'N'
|
|
||||||
AND LFD.STATUS = 3
|
|
||||||
AND LFD.MOVE_YN = 'Y'
|
|
||||||
LIMIT 1
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<update id="updateFileMoveSuccess" parameterType="com.alist.api.modules.tusFile.dto.FileMoveTaskDto">
|
|
||||||
/*FileMapper.updateFileMoveSuccess*/
|
|
||||||
UPDATE ALISTLMS.FILE_DETAIL
|
UPDATE ALISTLMS.FILE_DETAIL
|
||||||
SET SAVE_NAME = #{saveName}
|
SET SAVE_NAME = #{saveName}
|
||||||
, SAVE_PATH = #{savePath}
|
, SAVE_PATH = #{savePath}
|
||||||
@@ -288,8 +289,8 @@
|
|||||||
AND DEL_YN = 'N'
|
AND DEL_YN = 'N'
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<update id="updateFileMovePendingByFileUuid" parameterType="com.alist.api.modules.tusFile.dto.FileMoveTaskDto">
|
<update id="updateTusFileMovePending" parameterType="com.alist.api.modules.tusFile.dto.TusFileMoveTaskDto">
|
||||||
/*FileMapper.updateFileMovePendingByFileUuid*/
|
/*TusFileMapper.updateTusFileMovePending*/
|
||||||
UPDATE ALISTLMS.FILE_DETAIL
|
UPDATE ALISTLMS.FILE_DETAIL
|
||||||
SET MOVE_YN = 'N'
|
SET MOVE_YN = 'N'
|
||||||
, MOVE_TRY_COUNT = COALESCE(MOVE_TRY_COUNT, 0) + 1
|
, MOVE_TRY_COUNT = COALESCE(MOVE_TRY_COUNT, 0) + 1
|
||||||
@@ -300,36 +301,12 @@
|
|||||||
AND STATUS = 3
|
AND STATUS = 3
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<select id="selectFileDeleteTargetCount" resultType="java.lang.Integer">
|
<update id="updateTusFileDetailDelete">
|
||||||
/*FileMapper.selectFileDeleteTargetCount*/
|
/*TusFileMapper.updateTusFileDetailDelete*/
|
||||||
SELECT COUNT(*)
|
|
||||||
FROM ALISTLMS.FILE_DETAIL LFD
|
|
||||||
INNER JOIN ALISTLMS.FILE_MASTER LFM
|
|
||||||
ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
|
||||||
AND LFM.DEL_YN = 'N'
|
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
|
||||||
ON LTUT.user_idx = LFM.USER_IDX
|
|
||||||
WHERE LFD.FILE_UUID = #{fileUuid}
|
|
||||||
AND LTUT.user_token_idx = #{userTokenIdx}
|
|
||||||
AND LFD.DEL_YN = 'N'
|
|
||||||
AND LFD.STATUS = 3
|
|
||||||
AND LFM.STATUS = 3
|
|
||||||
</select>
|
|
||||||
<select id="selectUserIdxByUserTokenIdx" resultType="java.lang.Integer">
|
|
||||||
/*FileMapper.selectUserIdxByUserTokenIdx*/
|
|
||||||
SELECT user_idx
|
|
||||||
FROM test_user_token
|
|
||||||
WHERE user_token_idx = #{userTokenIdx}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<update id="updateFileDetailDeleteByFileUuid">
|
|
||||||
/*FileMapper.updateFileDetailDeleteByFileUuid*/
|
|
||||||
UPDATE ALISTLMS.FILE_DETAIL LFD
|
UPDATE ALISTLMS.FILE_DETAIL LFD
|
||||||
INNER JOIN ALISTLMS.FILE_MASTER LFM
|
INNER JOIN ALISTLMS.FILE_MASTER LFM ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
||||||
ON LFM.FILE_MASTER_IDX = LFD.FILE_MASTER_IDX
|
|
||||||
AND LFM.DEL_YN = 'N'
|
AND LFM.DEL_YN = 'N'
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFM.USER_IDX
|
||||||
ON LTUT.user_idx = LFM.USER_IDX
|
|
||||||
SET LFD.DEL_YN = 'Y'
|
SET LFD.DEL_YN = 'Y'
|
||||||
, LFD.UPDATE_DATE = NOW()
|
, LFD.UPDATE_DATE = NOW()
|
||||||
WHERE LFD.FILE_UUID = #{fileUuid}
|
WHERE LFD.FILE_UUID = #{fileUuid}
|
||||||
@@ -339,8 +316,8 @@
|
|||||||
AND LFM.STATUS = 3
|
AND LFM.STATUS = 3
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<update id="updateFileMasterDeleteByFileUuid">
|
<update id="updateTusFileMasterDelete">
|
||||||
/*FileMapper.updateFileMasterDeleteByFileUuid*/
|
/*TusFileMapper.updateTusFileMasterDelete*/
|
||||||
UPDATE ALISTLMS.FILE_MASTER LFM
|
UPDATE ALISTLMS.FILE_MASTER LFM
|
||||||
INNER JOIN (
|
INNER JOIN (
|
||||||
SELECT LFD.FILE_MASTER_IDX
|
SELECT LFD.FILE_MASTER_IDX
|
||||||
@@ -348,8 +325,7 @@
|
|||||||
WHERE LFD.FILE_UUID = #{fileUuid}
|
WHERE LFD.FILE_UUID = #{fileUuid}
|
||||||
AND LFD.DEL_YN = 'Y'
|
AND LFD.DEL_YN = 'Y'
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
) TARGET
|
) TARGET ON TARGET.FILE_MASTER_IDX = LFM.FILE_MASTER_IDX
|
||||||
ON TARGET.FILE_MASTER_IDX = LFM.FILE_MASTER_IDX
|
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
INNER JOIN ALISTLMS.test_user_token LTUT
|
||||||
ON LTUT.user_idx = LFM.USER_IDX
|
ON LTUT.user_idx = LFM.USER_IDX
|
||||||
SET LFM.DEL_YN = 'Y'
|
SET LFM.DEL_YN = 'Y'
|
||||||
@@ -365,4 +341,16 @@
|
|||||||
)
|
)
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<update id="updateTusFileUploadCancel">
|
||||||
|
/*TusFileMapper.updateTusFileUploadCancel*/
|
||||||
|
UPDATE ALISTLMS.FILE_DETAIL LFD
|
||||||
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFD.CREATE_MEMBER
|
||||||
|
SET LFD.STATUS = 5
|
||||||
|
, LFD.UPDATE_DATE = NOW()
|
||||||
|
WHERE LFD.DEL_YN = 'N'
|
||||||
|
AND LFD.FILE_UUID = #{fileUuid}
|
||||||
|
AND LTUT.user_token_idx = #{userTokenIdx}
|
||||||
|
AND LFD.STATUS IN (0,1,2)
|
||||||
|
</update>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
Reference in New Issue
Block a user