[파일 업로드] tusHook 작업

- 리줌 키로 다른 파일 올릴때 막기
This commit is contained in:
2026-03-09 15:29:26 +09:00
parent 2275c857e9
commit 6733aafd79
6 changed files with 121 additions and 1 deletions
@@ -1,10 +1,12 @@
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.FileUploadDto;
import com.alist.api.common.modules.file.dto.UploadCancelDto;
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.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.UploadCancelForm;
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;
import com.alist.api.common.response.ApiResponseCode; import com.alist.api.common.response.ApiResponseCode;
@@ -112,4 +114,30 @@ public class FileController {
return ApiResponse.entity("", ApiResponseCode.CODE_200); return ApiResponse.entity("", ApiResponseCode.CODE_200);
} }
@PostMapping("/uploadCancel")
public ResponseEntity<ApiResponse<String>> uploadCancel(
@Valid @RequestBody UploadCancelForm uploadCancelForm,
HttpServletRequest request
) {
HttpSession session = request.getSession(false);
Integer userTokenIdx = (session == null) ? null : (Integer) session.getAttribute("userTokenIdx");
if (userTokenIdx == null) {
return ApiResponse.entity("", ApiResponseCode.CODE_401);
}
UploadCancelDto uploadCancelDto = new UploadCancelDto();
uploadCancelDto.setFileUuid(uploadCancelForm.getFileUuid().trim());
uploadCancelDto.setUserTokenIdx(userTokenIdx);
boolean canceled = fileService.updateUploadCancel(uploadCancelDto);
if (!canceled) {
return ApiResponse.entity("", ApiResponseCode.CODE_403);
}
return ApiResponse.entity("", ApiResponseCode.CODE_200);
}
} }
@@ -0,0 +1,14 @@
package com.alist.api.common.modules.file.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UploadCancelDto {
private Integer userTokenIdx;
private String fileUuid;
private Long uploadedBytes;
private Long sizeBytes;
}
@@ -0,0 +1,12 @@
package com.alist.api.common.modules.file.form;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UploadCancelForm {
@NotBlank
private String fileUuid;
}
@@ -26,4 +26,10 @@ public interface FileMapper {
void updateTusUploadIdIfNull(FileUploadMetaDto fileUploadMetaDto); void updateTusUploadIdIfNull(FileUploadMetaDto fileUploadMetaDto);
void updateFileDetailCanceledByFileUuid(String fileUuid); void updateFileDetailCanceledByFileUuid(String fileUuid);
int selectFileDetailCountByFileUuidAndUserToKenIdx(UploadCancelDto uploadCancelDto);
int updateFileDetailCanceledByFileUuidAndUserTokenIdx(UploadCancelDto uploadCancelDto);
UploadCancelDto selectUploadProgressByFileUuid(UploadCancelDto uploadCancelDto);
} }
@@ -421,4 +421,29 @@ public class FileService {
} }
return false; return false;
} }
@Transactional
public boolean updateUploadCancel(UploadCancelDto uploadCancelDto) {
if (uploadCancelDto.getFileUuid() == null || uploadCancelDto.getFileUuid().isBlank() || uploadCancelDto.getUserTokenIdx() == null) {
return false;
}
int allowed = fileMapper.selectFileDetailCountByFileUuidAndUserToKenIdx(uploadCancelDto);
if (allowed <= 0) {
return false;
}
UploadCancelDto progress = fileMapper.selectUploadProgressByFileUuid(uploadCancelDto);
long uploaded = (progress != null && progress.getUploadedBytes() != null) ? progress.getUploadedBytes() : 0L;
long total = (progress != null && progress.getSizeBytes() != null) ? progress.getSizeBytes() : 0L;
int updated = fileMapper.updateFileDetailCanceledByFileUuidAndUserTokenIdx(uploadCancelDto);
if (updated <= 0) {
return false;
}
fileMapper.updateFileMasterAggregateByFileUuid(uploadCancelDto.getFileUuid());
saveCanceledStatusRedis(uploadCancelDto.getFileUuid(), uploaded, total); // 필요하면 기존 bytes 조회해서 넣어도 됨
return true;
}
} }
@@ -114,7 +114,17 @@
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="selectFileMasterCountByFileMasterKeyAndDelYnAndStatus" resultType="int"> <select id="selectFileMasterCountByFileMasterKeyAndDelYnAndStatus" resultType="int">
/*FileMapper.selectFileMasterCountByFileMasterKeyAndDelYnAndStatus*/ /*FileMapper.selectFileMasterCountByFileMasterKeyAndDelYnAndStatus*/
@@ -126,6 +136,7 @@
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"> <select id="selectFileDetailCountByFileUuidUserToKenIdx" resultType="java.lang.Integer">
/*FileMapper.selectFileDetailCountByFileUuidUserToKenIdx*/ /*FileMapper.selectFileDetailCountByFileUuidUserToKenIdx*/
SELECT COUNT(*) SELECT COUNT(*)
@@ -143,6 +154,7 @@
OR LOWER(LFD.CONTENT_TYPE) = LOWER(#{contentType}) OR LOWER(LFD.CONTENT_TYPE) = LOWER(#{contentType})
) )
</select> </select>
<select id="selectFileUploadMetaByFileUuid" resultType="com.alist.api.common.modules.file.dto.FileUploadMetaDto"> <select id="selectFileUploadMetaByFileUuid" resultType="com.alist.api.common.modules.file.dto.FileUploadMetaDto">
/*FileMapper.selectFileUploadMetaByFileUuid*/ /*FileMapper.selectFileUploadMetaByFileUuid*/
SELECT FILE_UUID, ORIGIN_NAME, SIZE_BYTES, CONTENT_TYPE, TUS_UPLOAD_ID, STATUS SELECT FILE_UUID, ORIGIN_NAME, SIZE_BYTES, CONTENT_TYPE, TUS_UPLOAD_ID, STATUS
@@ -151,4 +163,27 @@
AND DEL_YN = 'N' AND DEL_YN = 'N'
LIMIT 1 LIMIT 1
</select> </select>
<select id="selectFileDetailCountByFileUuidAndUserToKenIdx" resultType="java.lang.Integer">
/*FileMapper.selectCancelableUploadCountByFileUuidAndUserTokenIdx*/
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.common.modules.file.dto.UploadCancelDto">
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>
</mapper> </mapper>