[파일 업로드] tusHook 작업
- 멀티업로드 상태 업로드
This commit is contained in:
@@ -102,21 +102,9 @@ public class FileController {
|
|||||||
|
|
||||||
@PostMapping("/tusHook")
|
@PostMapping("/tusHook")
|
||||||
public ResponseEntity<ApiResponse<String>> tusHook(@RequestBody TusHookForm tusHookForm) {
|
public ResponseEntity<ApiResponse<String>> tusHook(@RequestBody TusHookForm tusHookForm) {
|
||||||
// log.info("tusHookForm: {}", tusHookForm);
|
|
||||||
// fileService.insertFileAndSave(tusHookForm.tusHookDto());
|
|
||||||
log.info("[tusHook] type={}", tusHookForm.getType());
|
|
||||||
log.info("[tusHook] uploadId={}", tusHookForm.getTusHookEventForm().getTusHookUploadForm().getId());
|
|
||||||
log.info("[tusHook] size={}", tusHookForm.getTusHookEventForm().getTusHookUploadForm().getSize());
|
|
||||||
log.info("[tusHook] metaData={}", tusHookForm.getTusHookEventForm().getTusHookUploadForm().getMetaData());
|
|
||||||
|
|
||||||
log.info("[tusHookDto] type={}", tusHookForm.tusHookDto().getType());
|
fileService.updateFileUploadStatus(tusHookForm.tusHookDto());
|
||||||
log.info("[tusHookDto] uploadId={}", tusHookForm.tusHookDto().getUploadId());
|
fileService.saveUploadStatusRedisTusHook(tusHookForm.tusHookDto());
|
||||||
log.info("[tusHookDto] size={}", tusHookForm.tusHookDto().getSize());
|
|
||||||
log.info("[tusHookDto] fileUuid={}", tusHookForm.tusHookDto().getFileUuid());
|
|
||||||
log.info("[tusHookDto] filename={}", tusHookForm.tusHookDto().getFilename());
|
|
||||||
log.info("[tusHookDto] filetype={}", tusHookForm.tusHookDto().getFiletype());
|
|
||||||
|
|
||||||
fileService.saveUploadStatusFromTusHook(tusHookForm.tusHookDto());
|
|
||||||
|
|
||||||
return ApiResponse.entity("", ApiResponseCode.CODE_200);
|
return ApiResponse.entity("", ApiResponseCode.CODE_200);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,6 @@ public class TusHookDto {
|
|||||||
private String fileUuid;
|
private String fileUuid;
|
||||||
private String filename;
|
private String filename;
|
||||||
private String filetype;
|
private String filetype;
|
||||||
|
private long uploadedBytes;
|
||||||
|
private int status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import lombok.Setter;
|
|||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class UploadStatusDto {
|
public class UploadStatusDto {
|
||||||
private String fileMasterKey;
|
private String fileUuid;
|
||||||
private String status; // PENDING, UPLOADING, DONE, FAILED
|
private String status; // PENDING, UPLOADING, DONE, FAILED
|
||||||
private long uploadedBytes;
|
private long uploadedBytes;
|
||||||
private long totalBytes;
|
private long totalBytes;
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import lombok.Setter;
|
|||||||
@Setter
|
@Setter
|
||||||
public class UploadStatusForm {
|
public class UploadStatusForm {
|
||||||
@NotBlank
|
@NotBlank
|
||||||
private String fileMasterKey;
|
private String fileUuid;
|
||||||
|
|
||||||
public UploadStatusDto uploadStatusDto() {
|
public UploadStatusDto uploadStatusDto() {
|
||||||
UploadStatusDto uploadStatusDto = new UploadStatusDto();
|
UploadStatusDto uploadStatusDto = new UploadStatusDto();
|
||||||
uploadStatusDto.setFileMasterKey(this.fileMasterKey == null ? null : this.fileMasterKey.trim());
|
uploadStatusDto.setFileUuid(this.fileUuid == null ? null : this.fileUuid.trim());
|
||||||
return uploadStatusDto;
|
return uploadStatusDto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
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.*;
|
||||||
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.UploadTokenDto;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
@@ -17,4 +14,10 @@ public interface FileMapper {
|
|||||||
void insertFileDetailInit(FileUploadItemDto item);
|
void insertFileDetailInit(FileUploadItemDto item);
|
||||||
|
|
||||||
int selectFileDetailCountByFileUuidUserToKenIdx(UploadTokenDto uploadTokenDto);
|
int selectFileDetailCountByFileUuidUserToKenIdx(UploadTokenDto uploadTokenDto);
|
||||||
|
|
||||||
|
void insertFileUploadEventLog(TusHookDto tusHookDto);
|
||||||
|
|
||||||
|
void updateFileDetailStatus(TusHookDto tusHookDto);
|
||||||
|
|
||||||
|
void updateFileMasterAggregateByFileUuid(String fileUuid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,40 +119,62 @@ 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.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
UploadStatusDto dto = new UploadStatusDto();
|
uploadStatusDto.setFileUuid((String) map.getOrDefault("fileUuid", uploadStatusDto.getFileUuid()));
|
||||||
dto.setFileMasterKey((String) map.getOrDefault("fileMasterKey", uploadStatusDto.getFileMasterKey()));
|
uploadStatusDto.setStatus((String) map.getOrDefault("status", "PENDING"));
|
||||||
dto.setStatus((String) map.getOrDefault("status", "PENDING"));
|
uploadStatusDto.setUploadedBytes(parseLong(map.get("uploadedBytes")));
|
||||||
dto.setUploadedBytes(parseLong(map.get("uploadedBytes")));
|
uploadStatusDto.setTotalBytes(parseLong(map.get("totalBytes")));
|
||||||
dto.setTotalBytes(parseLong(map.get("totalBytes")));
|
uploadStatusDto.setPercent((int) parseLong(map.get("percent")));
|
||||||
dto.setPercent((int) parseLong(map.get("percent")));
|
uploadStatusDto.setUpdatedAt((String) map.getOrDefault("updatedAt", ""));
|
||||||
dto.setUpdatedAt((String) map.getOrDefault("updatedAt", ""));
|
|
||||||
|
|
||||||
return dto;
|
return uploadStatusDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveUploadStatusFromTusHook(TusHookDto tusHookDto) {
|
/*db에 상태값 저장*/
|
||||||
|
public void updateFileUploadStatus(TusHookDto tusHookDto) {
|
||||||
|
if (tusHookDto == null || tusHookDto.getFileUuid() == null || tusHookDto.getFileUuid().isBlank()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String type = tusHookDto.getType() == null ? "" : tusHookDto.getType().trim().toLowerCase();
|
||||||
|
long offset = tusHookDto.getOffset() == null ? 0L : tusHookDto.getOffset();
|
||||||
|
long size = tusHookDto.getSize() == null ? 0L : tusHookDto.getSize();
|
||||||
|
|
||||||
|
fileMapper.insertFileUploadEventLog(tusHookDto);
|
||||||
|
|
||||||
|
tusHookDto.setUploadedBytes(offset);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "pre-create", "post-receive":
|
||||||
|
tusHookDto.setStatus(1); // UPLOADING
|
||||||
|
break;
|
||||||
|
case "post-finish":
|
||||||
|
tusHookDto.setStatus(3); // DONE
|
||||||
|
tusHookDto.setUploadedBytes(size);
|
||||||
|
break;
|
||||||
|
case "post-terminate":
|
||||||
|
tusHookDto.setStatus(5); // CANCELED (정책에 따라 FAILED=4)
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileMapper.updateFileDetailStatus(tusHookDto);
|
||||||
|
|
||||||
|
if ("post-finish".equals(type) || "post-terminate".equals(type)) {
|
||||||
|
fileMapper.updateFileMasterAggregateByFileUuid(tusHookDto.getFileUuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*레이디스에 상태값 저장*/
|
||||||
|
public void saveUploadStatusRedisTusHook(TusHookDto tusHookDto) {
|
||||||
if (tusHookDto == null || tusHookDto.getFileUuid() == null || tusHookDto.getFileUuid().isBlank()) {
|
if (tusHookDto == null || tusHookDto.getFileUuid() == null || tusHookDto.getFileUuid().isBlank()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -186,10 +208,6 @@ public class FileService {
|
|||||||
stringRedisTemplate.expire(key, Duration.ofHours(24));
|
stringRedisTemplate.expire(key, Duration.ofHours(24));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertFileAndSave(TusHookDto tusHookDto) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildUploadStatusKey(String fileUuid) {
|
private String buildUploadStatusKey(String fileUuid) {
|
||||||
return "upload:alist:status:" + fileUuid;
|
return "upload:alist:status:" + fileUuid;
|
||||||
}
|
}
|
||||||
@@ -217,7 +235,7 @@ public class FileService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void evictUploadAuthCacheByFileMasterKey(String fileUuid) {
|
private void evictUploadAuthCacheByFileUuid(String fileUuid) {
|
||||||
try {
|
try {
|
||||||
String pattern = "upload:alist:auth:" + fileUuid + ":*";
|
String pattern = "upload:alist:auth:" + fileUuid + ":*";
|
||||||
var keys = stringRedisTemplate.keys(pattern);
|
var keys = stringRedisTemplate.keys(pattern);
|
||||||
|
|||||||
@@ -30,6 +30,74 @@
|
|||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
<insert id="insertFileUploadEventLog">
|
||||||
|
/*FileMapper.insertFileUploadEventLog*/
|
||||||
|
INSERT INTO ALISTLMS.FILE_UPLOAD_EVENT_LOG (
|
||||||
|
FILE_DETAIL_IDX, EVENT_TYPE, OFFSET_BYTES, BYTES_WRITTEN, HTTP_STATUS, MESSAGE, RAW_JSON
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
LFD.FILE_DETAIL_IDX
|
||||||
|
, #{type}
|
||||||
|
, #{offset}
|
||||||
|
, NULL
|
||||||
|
, NULL
|
||||||
|
, NULL
|
||||||
|
, NULL
|
||||||
|
FROM ALISTLMS.FILE_DETAIL LFD
|
||||||
|
WHERE LFD.FILE_UUID = #{fileUuid}
|
||||||
|
LIMIT 1
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updateFileDetailStatus">
|
||||||
|
/*FileMapper.updateFileDetailStatus*/
|
||||||
|
UPDATE ALISTLMS.FILE_DETAIL
|
||||||
|
<set>
|
||||||
|
<if test="uploadId != null and uploadId != ''">
|
||||||
|
TUS_UPLOAD_ID = #{uploadId},
|
||||||
|
</if>
|
||||||
|
<if test="uploadedBytes != null">
|
||||||
|
UPLOADED_BYTES = #{uploadedBytes},
|
||||||
|
</if>
|
||||||
|
<if test="status != null">
|
||||||
|
STATUS = #{status},
|
||||||
|
</if>
|
||||||
|
UPDATE_DATE = NOW()
|
||||||
|
</set>
|
||||||
|
WHERE FILE_UUID = #{fileUuid}
|
||||||
|
AND DEL_YN = 'N'
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="updateFileMasterAggregateByFileUuid">
|
||||||
|
/*FileMapper.updateFileMasterAggregateByFileUuid*/
|
||||||
|
UPDATE ALISTLMS.FILE_MASTER LFM
|
||||||
|
JOIN (
|
||||||
|
SELECT
|
||||||
|
LLFD.FILE_MASTER_IDX,
|
||||||
|
COUNT(*) AS total_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
|
||||||
|
FROM ALISTLMS.FILE_DETAIL LLFD
|
||||||
|
WHERE LLFD.FILE_MASTER_IDX = (
|
||||||
|
SELECT FILE_MASTER_IDX
|
||||||
|
FROM ALISTLMS.FILE_DETAIL
|
||||||
|
WHERE FILE_UUID = #{fileUuid}
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
AND LLFD.DEL_YN = 'N'
|
||||||
|
) A ON A.FILE_MASTER_IDX = LFM.FILE_MASTER_IDX
|
||||||
|
SET LFM.TOTAL_COUNT = A.total_count,
|
||||||
|
LFM.DONE_COUNT = A.done_count,
|
||||||
|
LFM.FAIL_COUNT = A.fail_count,
|
||||||
|
LFM.STATUS = CASE
|
||||||
|
WHEN A.done_count = A.total_count THEN 3
|
||||||
|
WHEN A.done_count = 0 AND A.fail_count = A.total_count THEN 4
|
||||||
|
WHEN A.done_count > 0 AND A.fail_count > 0 THEN 5
|
||||||
|
ELSE 1
|
||||||
|
END,
|
||||||
|
LFM.UPDATE_DATE = NOW()
|
||||||
|
</update>
|
||||||
|
|
||||||
|
|
||||||
<select id="selectFileMasterCountByFileMasterKeyAndDelYnAndStatus" resultType="int">
|
<select id="selectFileMasterCountByFileMasterKeyAndDelYnAndStatus" resultType="int">
|
||||||
/*FileMapper.selectFileMasterCountByFileMasterKeyAndDelYnAndStatus*/
|
/*FileMapper.selectFileMasterCountByFileMasterKeyAndDelYnAndStatus*/
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
|
|||||||
Reference in New Issue
Block a user