[파일 업로드] tusHook 작업
- 리줌 키로 다른 파일 올릴때 막기
This commit is contained in:
@@ -64,6 +64,8 @@ public class FileController {
|
|||||||
public ResponseEntity<ApiResponse<String>> uploadAuth(
|
public ResponseEntity<ApiResponse<String>> uploadAuth(
|
||||||
@RequestHeader(value = "Authorization", required = false) String uploadToken
|
@RequestHeader(value = "Authorization", required = false) String uploadToken
|
||||||
, @RequestHeader(value = "x-File-Uuid", required = false) String fileUuid
|
, @RequestHeader(value = "x-File-Uuid", required = false) String fileUuid
|
||||||
|
, @RequestHeader(value = "Upload-Metadata", required = false) String uploadMetadata
|
||||||
|
, @RequestHeader(value = "Upload-Length", required = false) String uploadLength
|
||||||
) {
|
) {
|
||||||
if (uploadToken == null || !uploadToken.startsWith("Bearer ")) {
|
if (uploadToken == null || !uploadToken.startsWith("Bearer ")) {
|
||||||
return ApiResponse.entity("", ApiResponseCode.CODE_401);
|
return ApiResponse.entity("", ApiResponseCode.CODE_401);
|
||||||
@@ -75,6 +77,8 @@ public class FileController {
|
|||||||
UploadTokenDto uploadTokenDto = new UploadTokenDto();
|
UploadTokenDto uploadTokenDto = new UploadTokenDto();
|
||||||
uploadTokenDto.setUploadToken(uploadToken.substring(7).trim());
|
uploadTokenDto.setUploadToken(uploadToken.substring(7).trim());
|
||||||
uploadTokenDto.setFileUuid(fileUuid.trim());
|
uploadTokenDto.setFileUuid(fileUuid.trim());
|
||||||
|
uploadTokenDto.setUploadMetadataRaw(uploadMetadata);
|
||||||
|
uploadTokenDto.setUploadLengthRaw(uploadLength);
|
||||||
|
|
||||||
UploadTokenDto uploadTokenCheck = fileService.isUploadTokenCheck(uploadTokenDto);
|
UploadTokenDto uploadTokenCheck = fileService.isUploadTokenCheck(uploadTokenDto);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ public class UploadTokenDto {
|
|||||||
private String fileUuid;
|
private String fileUuid;
|
||||||
private String uploadToken;
|
private String uploadToken;
|
||||||
|
|
||||||
|
private String uploadMetadataRaw;
|
||||||
|
private String uploadLengthRaw;
|
||||||
|
|
||||||
|
private String originName;
|
||||||
|
private Long sizeBytes;
|
||||||
|
private String contentType;
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private int resultCode;
|
private int resultCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,9 @@ public class FileService {
|
|||||||
return uploadTokenDto;
|
return uploadTokenDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
String cacheKey = buildAuthCacheKey(uploadTokenDto.getFileUuid(), uploadTokenDto.getUploadToken());
|
applyTusMeta(uploadTokenDto);
|
||||||
|
|
||||||
|
String cacheKey = buildAuthCacheKey(uploadTokenDto);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String cached = stringRedisTemplate.opsForValue().get(cacheKey);
|
String cached = stringRedisTemplate.opsForValue().get(cacheKey);
|
||||||
@@ -122,6 +124,34 @@ public class FileService {
|
|||||||
return uploadTokenDto;
|
return uploadTokenDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyTusMeta(UploadTokenDto dto) {
|
||||||
|
String len = dto.getUploadLengthRaw();
|
||||||
|
if (len != null && !len.isBlank()) {
|
||||||
|
try { dto.setSizeBytes(Long.parseLong(len.trim())); } catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
String raw = dto.getUploadMetadataRaw();
|
||||||
|
if (raw == null || raw.isBlank()) return;
|
||||||
|
|
||||||
|
for (String part : raw.split(",")) {
|
||||||
|
String p = part.trim();
|
||||||
|
int sp = p.indexOf(' ');
|
||||||
|
if (sp <= 0) continue;
|
||||||
|
|
||||||
|
String key = p.substring(0, sp).trim();
|
||||||
|
String val = p.substring(sp + 1).trim();
|
||||||
|
String decoded;
|
||||||
|
try {
|
||||||
|
decoded = new String(java.util.Base64.getDecoder().decode(val), java.nio.charset.StandardCharsets.UTF_8);
|
||||||
|
} catch (Exception e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("filename".equals(key)) dto.setOriginName(decoded);
|
||||||
|
else if ("filetype".equals(key)) dto.setContentType(decoded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public UploadStatusDto getUploadStatus(UploadStatusDto uploadStatusDto) {
|
public UploadStatusDto getUploadStatus(UploadStatusDto uploadStatusDto) {
|
||||||
String key = buildUploadStatusKey(uploadStatusDto.getFileUuid());
|
String key = buildUploadStatusKey(uploadStatusDto.getFileUuid());
|
||||||
Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(key);
|
Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(key);
|
||||||
@@ -341,8 +371,24 @@ public class FileService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildAuthCacheKey(String fileUuid, String uploadToken) {
|
private String buildAuthCacheKey(UploadTokenDto dto) {
|
||||||
return "upload:alist:auth:" + fileUuid + ":" + sha256(uploadToken);
|
String normalizedName = normalize(dto.getOriginName());
|
||||||
|
String normalizedType = normalize(dto.getContentType());
|
||||||
|
String normalizedSize = (dto.getSizeBytes() == null) ? "" : String.valueOf(dto.getSizeBytes());
|
||||||
|
|
||||||
|
String raw = String.join("|",
|
||||||
|
normalize(dto.getFileUuid()),
|
||||||
|
dto.getUploadToken() == null ? "" : dto.getUploadToken(),
|
||||||
|
normalizedName,
|
||||||
|
normalizedType,
|
||||||
|
normalizedSize
|
||||||
|
);
|
||||||
|
|
||||||
|
return "upload:alist:auth:" + sha256(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String normalize(String v) {
|
||||||
|
return (v == null) ? "" : v.trim().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String sha256(String value) {
|
private String sha256(String value) {
|
||||||
@@ -355,18 +401,6 @@ public class FileService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void evictUploadAuthCacheByFileUuid(String fileUuid) {
|
|
||||||
try {
|
|
||||||
String pattern = "upload:alist:auth:" + fileUuid + ":*";
|
|
||||||
var keys = stringRedisTemplate.keys(pattern);
|
|
||||||
if (!keys.isEmpty()) {
|
|
||||||
stringRedisTemplate.delete(keys);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("uploadAuth cache evict fail. fileUuid={}", fileUuid, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private long safeTtlSeconds() {
|
private long safeTtlSeconds() {
|
||||||
// 설정 실수 방어: 0/음수면 기본값 20초 사용
|
// 설정 실수 방어: 0/음수면 기본값 20초 사용
|
||||||
return (uploadAuthCacheTtlSeconds > 0) ? uploadAuthCacheTtlSeconds : 20L;
|
return (uploadAuthCacheTtlSeconds > 0) ? uploadAuthCacheTtlSeconds : 20L;
|
||||||
|
|||||||
@@ -130,12 +130,18 @@
|
|||||||
/*FileMapper.selectFileDetailCountByFileUuidUserToKenIdx*/
|
/*FileMapper.selectFileDetailCountByFileUuidUserToKenIdx*/
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
FROM ALISTLMS.FILE_DETAIL LFD
|
FROM ALISTLMS.FILE_DETAIL LFD
|
||||||
INNER JOIN ALISTLMS.test_user_token LTUT
|
INNER JOIN ALISTLMS.test_user_token LTUT ON LTUT.user_idx = LFD.CREATE_MEMBER
|
||||||
ON LTUT.user_idx = LFD.CREATE_MEMBER
|
|
||||||
WHERE LFD.DEL_YN = 'N'
|
WHERE LFD.DEL_YN = 'N'
|
||||||
AND LFD.FILE_UUID = #{fileUuid}
|
AND LFD.FILE_UUID = #{fileUuid}
|
||||||
AND LFD.STATUS IN (0,1,2,3) <!-- 정책에 맞게 조정 -->
|
|
||||||
AND LTUT.user_token_idx = #{userTokenIdx}
|
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>
|
||||||
<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*/
|
||||||
|
|||||||
Reference in New Issue
Block a user