[파일 업로드] tusHook 작업
- 멀티업로드 변경
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
package com.alist.api.common.modules.file;
|
package com.alist.api.common.modules.file;
|
||||||
|
|
||||||
|
import com.alist.api.common.modules.file.dto.FileUploadDto;
|
||||||
import com.alist.api.common.modules.file.dto.UploadStatusDto;
|
import com.alist.api.common.modules.file.dto.UploadStatusDto;
|
||||||
import com.alist.api.common.modules.file.dto.UploadTokenDto;
|
import com.alist.api.common.modules.file.dto.UploadTokenDto;
|
||||||
|
import com.alist.api.common.modules.file.form.FileUploadForm;
|
||||||
import com.alist.api.common.modules.file.form.TusHookForm;
|
import com.alist.api.common.modules.file.form.TusHookForm;
|
||||||
import com.alist.api.common.modules.file.form.UploadStatusForm;
|
import com.alist.api.common.modules.file.form.UploadStatusForm;
|
||||||
import com.alist.api.common.response.ApiResponse;
|
import com.alist.api.common.response.ApiResponse;
|
||||||
@@ -18,8 +20,6 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Tag(name = "99. 파일 관리", description = "파일 관리")
|
@Tag(name = "99. 파일 관리", description = "파일 관리")
|
||||||
@RestController
|
@RestController
|
||||||
@@ -32,46 +32,51 @@ public class FileController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "파일 업로드 시작",
|
summary = "파일 업로드 준비(db 입력 및 업로드 토큰 생성)",
|
||||||
description = "업로드 토큰 획득 및 업로드 정보 db 기록"
|
description = "업로드 토큰 생성 및 파일 업로드 준비"
|
||||||
)
|
)
|
||||||
@PostMapping("/uploadStart")
|
@PostMapping("/uploadInit")
|
||||||
public ResponseEntity<ApiResponse<UploadStartDto>> uploadStart(
|
public ResponseEntity<ApiResponse<FileUploadDto>> uploadInit(
|
||||||
@Valid @RequestBody UploadStartForm uploadStartForm
|
@Valid @RequestBody FileUploadForm fileUploadForm
|
||||||
, HttpServletRequest request
|
, HttpServletRequest request
|
||||||
) {
|
) {
|
||||||
|
FileUploadDto fileUploadDto = fileUploadForm.fileUploadDto();
|
||||||
|
|
||||||
HttpSession session = request.getSession(false);
|
HttpSession session = request.getSession(false);
|
||||||
Integer userTokenIdx = (session == null) ? null : (Integer) session.getAttribute("userTokenIdx");
|
Integer userTokenIdx = (session == null) ? null : (Integer) session.getAttribute("userTokenIdx");
|
||||||
Integer userIdx = (session == null) ? null : (Integer) session.getAttribute("userIdx");
|
Integer userIdx = (session == null) ? null : (Integer) session.getAttribute("userIdx");
|
||||||
|
|
||||||
if (userTokenIdx == null || userIdx == null) {
|
if (userTokenIdx == null || userIdx == null) {
|
||||||
return ApiResponse.entity(new UploadStartDto(), ApiResponseCode.CODE_401);
|
return ApiResponse.entity(new FileUploadDto(), ApiResponseCode.CODE_401);
|
||||||
}
|
}
|
||||||
|
|
||||||
UploadStartDto uploadInitDto = fileService.insertFileMasterUpload(userIdx, userTokenIdx, uploadStartForm.uploadStartDto());
|
fileUploadDto.setUserIdx(userIdx);
|
||||||
|
fileUploadDto.setUserTokenIdx(userTokenIdx);
|
||||||
|
|
||||||
return ApiResponse.entity(uploadInitDto, ApiResponseCode.CODE_200);
|
FileUploadDto fileUploadResult = fileService.insertFileInit(fileUploadDto);
|
||||||
|
|
||||||
|
return ApiResponse.entity(fileUploadResult, ApiResponseCode.CODE_200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "업로드 권한 체크",
|
summary = "업로드 권한 체크",
|
||||||
description = "업로드 토큰 발급 후 실제 업로드 권한이 있는지 확인 과정입니다."
|
description = "업로드 토큰 발급 후 실제 업로드 권한이 있는지 확인 과정입니다."
|
||||||
)
|
)
|
||||||
@GetMapping("/uploadAuthCheck")
|
@GetMapping("/uploadAuth")
|
||||||
public ResponseEntity<ApiResponse<String>> uploadAuthCheck(
|
public ResponseEntity<ApiResponse<String>> uploadAuth(
|
||||||
@RequestHeader(value = "Authorization", required = false) String uploadToken
|
@RequestHeader(value = "Authorization", required = false) String uploadToken
|
||||||
, @RequestHeader(value = "X-File-Master-Key", required = false) String fileMasterKey
|
, @RequestHeader(value = "x-File-Uuid", required = false) String fileUuid
|
||||||
) {
|
) {
|
||||||
if (uploadToken == null || !uploadToken.startsWith("Bearer ")) {
|
if (uploadToken == null || !uploadToken.startsWith("Bearer ")) {
|
||||||
return ApiResponse.entity("", ApiResponseCode.CODE_401);
|
return ApiResponse.entity("", ApiResponseCode.CODE_401);
|
||||||
}
|
}
|
||||||
if (fileMasterKey == null || fileMasterKey.isBlank()) {
|
if (fileUuid == null || fileUuid.isBlank()) {
|
||||||
return ApiResponse.entity("", ApiResponseCode.CODE_403);
|
return ApiResponse.entity("", ApiResponseCode.CODE_403);
|
||||||
}
|
}
|
||||||
|
|
||||||
UploadTokenDto uploadTokenDto = new UploadTokenDto();
|
UploadTokenDto uploadTokenDto = new UploadTokenDto();
|
||||||
uploadTokenDto.setUploadToken(uploadToken.substring(7).trim());
|
uploadTokenDto.setUploadToken(uploadToken.substring(7).trim());
|
||||||
uploadTokenDto.setFileMasterKey(fileMasterKey.trim());
|
uploadTokenDto.setFileUuid(fileUuid.trim());
|
||||||
|
|
||||||
UploadTokenDto uploadTokenCheck = fileService.isUploadTokenCheck(uploadTokenDto);
|
UploadTokenDto uploadTokenCheck = fileService.isUploadTokenCheck(uploadTokenDto);
|
||||||
|
|
||||||
@@ -107,7 +112,7 @@ public class FileController {
|
|||||||
log.info("[tusHookDto] type={}", tusHookForm.tusHookDto().getType());
|
log.info("[tusHookDto] type={}", tusHookForm.tusHookDto().getType());
|
||||||
log.info("[tusHookDto] uploadId={}", tusHookForm.tusHookDto().getUploadId());
|
log.info("[tusHookDto] uploadId={}", tusHookForm.tusHookDto().getUploadId());
|
||||||
log.info("[tusHookDto] size={}", tusHookForm.tusHookDto().getSize());
|
log.info("[tusHookDto] size={}", tusHookForm.tusHookDto().getSize());
|
||||||
log.info("[tusHookDto] fileMasterKey={}", tusHookForm.tusHookDto().getFileMasterKey());
|
log.info("[tusHookDto] fileUuid={}", tusHookForm.tusHookDto().getFileUuid());
|
||||||
log.info("[tusHookDto] filename={}", tusHookForm.tusHookDto().getFilename());
|
log.info("[tusHookDto] filename={}", tusHookForm.tusHookDto().getFilename());
|
||||||
log.info("[tusHookDto] filetype={}", tusHookForm.tusHookDto().getFiletype());
|
log.info("[tusHookDto] filetype={}", tusHookForm.tusHookDto().getFiletype());
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.alist.api.common.modules.file.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class FileUploadDto {
|
||||||
|
private Long fileMasterIdx;
|
||||||
|
private String tusEndpoint;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private String fileCategory;
|
||||||
|
@JsonIgnore
|
||||||
|
private String folderPath;
|
||||||
|
@JsonIgnore
|
||||||
|
private Integer userTokenIdx;
|
||||||
|
@JsonIgnore
|
||||||
|
private Integer userIdx;
|
||||||
|
@JsonIgnore
|
||||||
|
private Integer status;
|
||||||
|
@JsonIgnore
|
||||||
|
private Integer totalCount;
|
||||||
|
|
||||||
|
private List<FileUploadItemDto> itemList;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.alist.api.common.modules.file.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class FileUploadItemDto {
|
||||||
|
private Integer fileSeq;
|
||||||
|
private String fileUuid;
|
||||||
|
private String uploadToken;
|
||||||
|
private String originName;
|
||||||
|
private Long sizeBytes;
|
||||||
|
private String contentType;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private Long fileMasterIdx;
|
||||||
|
@JsonIgnore
|
||||||
|
private Integer userIdx;
|
||||||
|
@JsonIgnore
|
||||||
|
private Integer status;
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ public class TusHookDto {
|
|||||||
private String uploadId;
|
private String uploadId;
|
||||||
private Long size;
|
private Long size;
|
||||||
private Long offset;
|
private Long offset;
|
||||||
private String fileMasterKey;
|
private String fileUuid;
|
||||||
private String filename;
|
private String filename;
|
||||||
private String filetype;
|
private String filetype;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import lombok.Setter;
|
|||||||
@Setter
|
@Setter
|
||||||
public class UploadTokenDto {
|
public class UploadTokenDto {
|
||||||
private Integer userTokenIdx;
|
private Integer userTokenIdx;
|
||||||
private String fileMasterKey;
|
private String fileUuid;
|
||||||
private String uploadToken;
|
private String uploadToken;
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.alist.api.common.modules.file.form;
|
||||||
|
|
||||||
|
import com.alist.api.common.modules.file.dto.FileUploadDto;
|
||||||
|
import com.alist.api.common.modules.file.dto.FileUploadItemDto;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class FileUploadForm {
|
||||||
|
@NotBlank
|
||||||
|
private String fileCategory;
|
||||||
|
|
||||||
|
private String folderPath;
|
||||||
|
|
||||||
|
@NotEmpty
|
||||||
|
@Valid
|
||||||
|
private List<FileUploadItemForm> itemList;
|
||||||
|
|
||||||
|
public FileUploadDto fileUploadDto() {
|
||||||
|
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,21 @@
|
|||||||
|
package com.alist.api.common.modules.file.form;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Positive;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class FileUploadItemForm {
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String originName;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Positive
|
||||||
|
private Long sizeBytes;
|
||||||
|
|
||||||
|
private String contentType;
|
||||||
|
}
|
||||||
@@ -31,7 +31,7 @@ public class TusHookForm {
|
|||||||
tusHookDto.setOffset(upload.getOffset());
|
tusHookDto.setOffset(upload.getOffset());
|
||||||
|
|
||||||
if (upload.getMetaData() != null) {
|
if (upload.getMetaData() != null) {
|
||||||
tusHookDto.setFileMasterKey(upload.getMetaData().get("fileMasterKey"));
|
tusHookDto.setFileUuid(upload.getMetaData().get("fileUuid"));
|
||||||
tusHookDto.setFilename(upload.getMetaData().get("filename"));
|
tusHookDto.setFilename(upload.getMetaData().get("filename"));
|
||||||
tusHookDto.setFiletype(upload.getMetaData().get("filetype"));
|
tusHookDto.setFiletype(upload.getMetaData().get("filetype"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import lombok.Setter;
|
|||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
public class UploadTokenForm {
|
public class UploadTokenForm {
|
||||||
private String fileMasterKey;
|
private String fileUuid;
|
||||||
private String uploadToken;
|
private String uploadToken;
|
||||||
|
|
||||||
public UploadTokenDto uploadTokenDto() {
|
public UploadTokenDto uploadTokenDto() {
|
||||||
UploadTokenDto uploadTokenDto = new UploadTokenDto();
|
UploadTokenDto uploadTokenDto = new UploadTokenDto();
|
||||||
uploadTokenDto.setFileMasterKey(this.fileMasterKey);
|
uploadTokenDto.setFileUuid(this.fileUuid);
|
||||||
uploadTokenDto.setUploadToken(this.uploadToken);
|
uploadTokenDto.setUploadToken(this.uploadToken);
|
||||||
|
|
||||||
return uploadTokenDto;
|
return uploadTokenDto;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.alist.api.common.modules.file.mapper;
|
package com.alist.api.common.modules.file.mapper;
|
||||||
|
|
||||||
|
import com.alist.api.common.modules.file.dto.FileUploadDto;
|
||||||
|
import com.alist.api.common.modules.file.dto.FileUploadItemDto;
|
||||||
import com.alist.api.common.modules.file.dto.UploadStartDto;
|
import com.alist.api.common.modules.file.dto.UploadStartDto;
|
||||||
import com.alist.api.common.modules.file.dto.UploadTokenDto;
|
import com.alist.api.common.modules.file.dto.UploadTokenDto;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
@@ -9,4 +11,10 @@ public interface FileMapper {
|
|||||||
void insertFileMasterUpload(UploadStartDto uploadStartDto);
|
void insertFileMasterUpload(UploadStartDto uploadStartDto);
|
||||||
|
|
||||||
int selectFileMasterCountByFileMasterKeyAndDelYnAndStatus(UploadTokenDto uploadTokenDto);
|
int selectFileMasterCountByFileMasterKeyAndDelYnAndStatus(UploadTokenDto uploadTokenDto);
|
||||||
|
|
||||||
|
void insertFileMasterInit(FileUploadDto fileUploadDto);
|
||||||
|
|
||||||
|
void insertFileDetailInit(FileUploadItemDto item);
|
||||||
|
|
||||||
|
int selectFileDetailCountByFileUuidUserToKenIdx(UploadTokenDto uploadTokenDto);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package com.alist.api.common.modules.file.service;
|
package com.alist.api.common.modules.file.service;
|
||||||
|
|
||||||
import com.alist.api.common.modules.file.dto.TusHookDto;
|
import com.alist.api.common.modules.file.dto.*;
|
||||||
import com.alist.api.common.modules.file.dto.UploadStartDto;
|
|
||||||
import com.alist.api.common.modules.file.dto.UploadStatusDto;
|
|
||||||
import com.alist.api.common.modules.file.dto.UploadTokenDto;
|
|
||||||
import com.alist.api.common.modules.file.mapper.FileMapper;
|
import com.alist.api.common.modules.file.mapper.FileMapper;
|
||||||
import com.alist.api.config.jwt.JwtTokenProvider;
|
import com.alist.api.config.jwt.JwtTokenProvider;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -11,6 +8,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.data.redis.core.HashOperations;
|
import org.springframework.data.redis.core.HashOperations;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
@@ -43,20 +41,32 @@ public class FileService {
|
|||||||
this.stringRedisTemplate = stringRedisTemplate;
|
this.stringRedisTemplate = stringRedisTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UploadStartDto insertFileMasterUpload(Integer userIdx, Integer userTokenIdx, UploadStartDto uploadStartDto) {
|
/*파일 초기화 작업*/
|
||||||
uploadStartDto.setFileMasterKey(UUID.randomUUID().toString());
|
@Transactional
|
||||||
uploadStartDto.setUserIdx(userIdx);
|
public FileUploadDto insertFileInit(FileUploadDto fileUploadDto) {
|
||||||
uploadStartDto.setStatus(1);
|
fileUploadDto.setStatus(0);
|
||||||
uploadStartDto.setFolderPath(uploadStartDto.getFolderPath() == null ? "/" : uploadStartDto.getFolderPath());
|
fileUploadDto.setTotalCount(fileUploadDto.getItemList().size());
|
||||||
|
|
||||||
fileMapper.insertFileMasterUpload(uploadStartDto);
|
fileMapper.insertFileMasterInit(fileUploadDto);
|
||||||
|
fileUploadDto.setTusEndpoint(tusEndpoint);
|
||||||
|
|
||||||
uploadStartDto.setUploadToken(jwtTokenProvider.createUploadToken(userTokenIdx));
|
if (fileUploadDto.getItemList() == null || fileUploadDto.getItemList().isEmpty()) {
|
||||||
uploadStartDto.setTusEndpoint(tusEndpoint);
|
return fileUploadDto;
|
||||||
|
|
||||||
return uploadStartDto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (FileUploadItemDto item : fileUploadDto.getItemList()) {
|
||||||
|
item.setFileMasterIdx(fileUploadDto.getFileMasterIdx());
|
||||||
|
item.setFileUuid(UUID.randomUUID().toString());
|
||||||
|
item.setUploadToken(jwtTokenProvider.createUploadToken(fileUploadDto.getUserTokenIdx()));
|
||||||
|
item.setUserIdx(fileUploadDto.getUserIdx());
|
||||||
|
item.setStatus(0); // PENDING
|
||||||
|
fileMapper.insertFileDetailInit(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileUploadDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*업로드 권한 체크*/
|
||||||
public UploadTokenDto isUploadTokenCheck(UploadTokenDto uploadTokenDto) {
|
public UploadTokenDto isUploadTokenCheck(UploadTokenDto uploadTokenDto) {
|
||||||
if (!jwtTokenProvider.validateToken(uploadTokenDto.getUploadToken())) {
|
if (!jwtTokenProvider.validateToken(uploadTokenDto.getUploadToken())) {
|
||||||
uploadTokenDto.setResultCode(401);
|
uploadTokenDto.setResultCode(401);
|
||||||
@@ -75,7 +85,7 @@ public class FileService {
|
|||||||
return uploadTokenDto;
|
return uploadTokenDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
String cacheKey = buildAuthCacheKey(uploadTokenDto.getFileMasterKey(), uploadTokenDto.getUploadToken());
|
String cacheKey = buildAuthCacheKey(uploadTokenDto.getFileUuid(), uploadTokenDto.getUploadToken());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String cached = stringRedisTemplate.opsForValue().get(cacheKey);
|
String cached = stringRedisTemplate.opsForValue().get(cacheKey);
|
||||||
@@ -92,7 +102,7 @@ public class FileService {
|
|||||||
log.warn("uploadAuth cache get fail. fallback DB. key={}", cacheKey, redisGetEx);
|
log.warn("uploadAuth cache get fail. fallback DB. key={}", cacheKey, redisGetEx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int isOk = fileMapper.selectFileMasterCountByFileMasterKeyAndDelYnAndStatus(uploadTokenDto);
|
int isOk = fileMapper.selectFileDetailCountByFileUuidUserToKenIdx(uploadTokenDto);
|
||||||
int resultCode = (isOk > 0) ? 200 : 403;
|
int resultCode = (isOk > 0) ? 200 : 403;
|
||||||
uploadTokenDto.setResultCode(resultCode);
|
uploadTokenDto.setResultCode(resultCode);
|
||||||
|
|
||||||
@@ -109,6 +119,20 @@ public class FileService {
|
|||||||
return uploadTokenDto;
|
return uploadTokenDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UploadStartDto insertFileMasterUpload(Integer userIdx, Integer userTokenIdx, UploadStartDto uploadStartDto) {
|
||||||
|
uploadStartDto.setFileMasterKey(UUID.randomUUID().toString());
|
||||||
|
uploadStartDto.setUserIdx(userIdx);
|
||||||
|
uploadStartDto.setStatus(1);
|
||||||
|
uploadStartDto.setFolderPath(uploadStartDto.getFolderPath() == null ? "/" : uploadStartDto.getFolderPath());
|
||||||
|
|
||||||
|
fileMapper.insertFileMasterUpload(uploadStartDto);
|
||||||
|
|
||||||
|
uploadStartDto.setUploadToken(jwtTokenProvider.createUploadToken(userTokenIdx));
|
||||||
|
uploadStartDto.setTusEndpoint(tusEndpoint);
|
||||||
|
|
||||||
|
return uploadStartDto;
|
||||||
|
}
|
||||||
|
|
||||||
public UploadStatusDto getUploadStatus(UploadStatusDto uploadStatusDto) {
|
public UploadStatusDto getUploadStatus(UploadStatusDto uploadStatusDto) {
|
||||||
String key = buildUploadStatusKey(uploadStatusDto.getFileMasterKey());
|
String key = buildUploadStatusKey(uploadStatusDto.getFileMasterKey());
|
||||||
Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(key);
|
Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(key);
|
||||||
@@ -129,11 +153,11 @@ public class FileService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void saveUploadStatusFromTusHook(TusHookDto tusHookDto) {
|
public void saveUploadStatusFromTusHook(TusHookDto tusHookDto) {
|
||||||
if (tusHookDto == null || tusHookDto.getFileMasterKey() == null || tusHookDto.getFileMasterKey().isBlank()) {
|
if (tusHookDto == null || tusHookDto.getFileUuid() == null || tusHookDto.getFileUuid().isBlank()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = buildUploadStatusKey(tusHookDto.getFileMasterKey().trim());
|
String key = buildUploadStatusKey(tusHookDto.getFileUuid().trim());
|
||||||
String type = tusHookDto.getType() == null ? "" : tusHookDto.getType().trim().toLowerCase();
|
String type = tusHookDto.getType() == null ? "" : tusHookDto.getType().trim().toLowerCase();
|
||||||
long total = tusHookDto.getSize() == null ? 0L : tusHookDto.getSize();
|
long total = tusHookDto.getSize() == null ? 0L : tusHookDto.getSize();
|
||||||
long uploaded = tusHookDto.getOffset() == null ? 0L : tusHookDto.getOffset();
|
long uploaded = tusHookDto.getOffset() == null ? 0L : tusHookDto.getOffset();
|
||||||
@@ -151,7 +175,7 @@ public class FileService {
|
|||||||
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, "fileMasterKey", tusHookDto.getFileMasterKey());
|
ops.put(key, "fileUuid", tusHookDto.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));
|
||||||
@@ -166,8 +190,8 @@ public class FileService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildUploadStatusKey(String fileMasterKey) {
|
private String buildUploadStatusKey(String fileUuid) {
|
||||||
return "upload:alist:status:" + fileMasterKey;
|
return "upload:alist:status:" + fileUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long parseLong(Object value) {
|
private long parseLong(Object value) {
|
||||||
@@ -179,8 +203,8 @@ public class FileService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildAuthCacheKey(String fileMasterKey, String uploadToken) {
|
private String buildAuthCacheKey(String fileUuid, String uploadToken) {
|
||||||
return "upload:alist:auth:" + fileMasterKey + ":" + sha256(uploadToken);
|
return "upload:alist:auth:" + fileUuid + ":" + sha256(uploadToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String sha256(String value) {
|
private String sha256(String value) {
|
||||||
@@ -193,15 +217,15 @@ public class FileService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void evictUploadAuthCacheByFileMasterKey(String fileMasterKey) {
|
private void evictUploadAuthCacheByFileMasterKey(String fileUuid) {
|
||||||
try {
|
try {
|
||||||
String pattern = "upload:alist:auth:" + fileMasterKey + ":*";
|
String pattern = "upload:alist:auth:" + fileUuid + ":*";
|
||||||
var keys = stringRedisTemplate.keys(pattern);
|
var keys = stringRedisTemplate.keys(pattern);
|
||||||
if (!keys.isEmpty()) {
|
if (!keys.isEmpty()) {
|
||||||
stringRedisTemplate.delete(keys);
|
stringRedisTemplate.delete(keys);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("uploadAuth cache evict fail. fileMasterKey={}", fileMasterKey, e);
|
log.warn("uploadAuth cache evict fail. fileUuid={}", fileUuid, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,28 @@
|
|||||||
<!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.common.modules.file.mapper.FileMapper">
|
<mapper namespace="com.alist.api.common.modules.file.mapper.FileMapper">
|
||||||
|
|
||||||
|
<insert id="insertFileMasterInit" useGeneratedKeys="true" keyProperty="fileMasterIdx">
|
||||||
|
/*FileMapper.insertFileMasterInit*/
|
||||||
|
INSERT INTO ALISTLMS.FILE_MASTER (
|
||||||
|
USER_IDX, FILE_CATEGORY, FOLDER_PATH, TOTAL_COUNT, DONE_COUNT, FAIL_COUNT, STATUS, DEL_YN, CREATE_MEMBER, UPDATE_MEMBER
|
||||||
|
) VALUES (
|
||||||
|
#{userIdx}, #{fileCategory}, #{folderPath}, #{totalCount}, 0, 0, #{status}, 'N', #{userIdx}, #{userIdx}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<insert id="insertFileDetailInit">
|
||||||
|
/*FileMapper.insertFileDetailInit*/
|
||||||
|
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
|
||||||
|
) VALUES (
|
||||||
|
#{fileMasterIdx}, #{fileSeq}, #{fileUuid}, #{originName}, #{contentType}, #{sizeBytes}, 0, NULL, #{status}, 'N', #{userIdx}, #{userIdx}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
<insert id="insertFileMasterUpload">
|
<insert id="insertFileMasterUpload">
|
||||||
/*FileMapper.insertFileMasterUpload*/
|
/*FileMapper.insertFileMasterUpload*/
|
||||||
INSERT INTO ALISTLMS.FILE_MASTER (
|
INSERT INTO ALISTLMS.FILE_MASTER2 (
|
||||||
FILE_MASTER_KEY, USER_IDX, FILE_CATEGORY, FOLDER_PATH, STATUS, CREATE_MEMBER, UPDATE_MEMBER
|
FILE_MASTER_KEY, USER_IDX, FILE_CATEGORY, FOLDER_PATH, STATUS, CREATE_MEMBER, UPDATE_MEMBER
|
||||||
) values (
|
) values (
|
||||||
#{fileMasterKey}, #{userIdx}, #{fileCategory}, #{folderPath}, #{status}, #{userIdx}, #{userIdx}
|
#{fileMasterKey}, #{userIdx}, #{fileCategory}, #{folderPath}, #{status}, #{userIdx}, #{userIdx}
|
||||||
@@ -14,11 +33,22 @@
|
|||||||
<select id="selectFileMasterCountByFileMasterKeyAndDelYnAndStatus" resultType="int">
|
<select id="selectFileMasterCountByFileMasterKeyAndDelYnAndStatus" resultType="int">
|
||||||
/*FileMapper.selectFileMasterCountByFileMasterKeyAndDelYnAndStatus*/
|
/*FileMapper.selectFileMasterCountByFileMasterKeyAndDelYnAndStatus*/
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
FROM ALISTLMS.FILE_MASTER LFM
|
FROM ALISTLMS.FILE_MASTER2 LFM
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFM.USER_IDX
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFM.USER_IDX
|
||||||
WHERE LFM.DEL_YN = 'N'
|
WHERE LFM.DEL_YN = 'N'
|
||||||
AND LFM.FILE_MASTER_KEY = #{fileMasterKey}
|
AND LFM.FILE_MASTER_KEY = #{fileMasterKey}
|
||||||
AND LFM.STATUS = 1
|
AND LFM.STATUS = 1
|
||||||
AND LTUT.user_token_idx = #{userTokenIdx}
|
AND LTUT.user_token_idx = #{userTokenIdx}
|
||||||
</select>
|
</select>
|
||||||
|
<select id="selectFileDetailCountByFileUuidUserToKenIdx" resultType="java.lang.Integer">
|
||||||
|
/*FileMapper.selectFileDetailCountByFileUuidUserToKenIdx*/
|
||||||
|
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 LFD.STATUS IN (0,1,2,3) <!-- 정책에 맞게 조정 -->
|
||||||
|
AND LTUT.user_token_idx = #{userTokenIdx}
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
Reference in New Issue
Block a user