package architecture.web.spring.web.controller.data.secure.mgmt.resources; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import architecture.ee.exception.NotFoundException; import architecture.user.User; import architecture.user.util.SecurityHelper; import architecture.web.attachments.Attachment; import architecture.web.attachments.AttachmentService; import architecture.web.attachments.DefaultAttachment; import architecture.web.attachments.dao.jpa.LocalAttachment; import architecture.web.model.Models; import architecture.web.share.SharedLinkService; import architecture.web.spring.web.controller.data.upload.AbstractTusUploadDataController; import architecture.web.spring.web.controller.data.upload.TusFileUploadStatus; import architecture.web.spring.web.controller.data.upload.TusHttpHeader; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @Slf4j @RequestMapping(TusUploadDataController.TUS_REQUEST_URL) @Tag(name = "mgmt files", description = "File Management APIs") @RestController("controllers:mgmt:tus-upload-data-controller") public class TusUploadDataController extends AbstractTusUploadDataController { public static final String TUS_REQUEST_URL = "/data/secure/mgmt/resources/files"; final AttachmentService attachmentService; final SharedLinkService sharedLinkService; TusUploadDataController( @Qualifier(AttachmentService.SERVICE_NAME) AttachmentService attachmentService, @Autowired(required = false) @Qualifier(SharedLinkService.SERVICE_NAME) SharedLinkService sharedLinkService ) { this.attachmentService = attachmentService; this.sharedLinkService = sharedLinkService; } protected AttachmentService getAttachmentService() { return attachmentService; } protected String getUrlPrefix() { return TUS_REQUEST_URL; } protected void doUploadComplete(File file, TusFileUploadStatus status) throws NotFoundException, IOException { String contentType = Optional.ofNullable(status.getMeta().get("filetype")) .map(Object::toString) .orElse("application/octet-stream"); // 기본값을 application/octet-stream 설정 long attachmentId = Optional.ofNullable(status.getMeta().get("attachmentId")) .map(Object::toString) .map(Long::parseLong) .orElse(0L); // 기본값을 0 설정 int objectType = Optional.ofNullable(status.getMeta().get("objectType")) .map(Object::toString) .map(Integer::parseInt) .orElse(0); // 기본값을 0 설정 long objectId = Optional.ofNullable(status.getMeta().get("objectId")) .map(Object::toString) .map(Long::parseLong) .orElse(0L); // 기본값을 0 설정 boolean link = Optional.ofNullable(status.getMeta().get("link")) .map(Object::toString) .map(Boolean::parseBoolean) .orElse(false); // 기본값을 false 설정 FileInputStream inputStream = new FileInputStream(file); Attachment attachment; boolean isUpdate = attachmentId > 0 ? true : false; if (isUpdate) { attachment = attachmentService.getAttachment(attachmentId); attachment.setContentType(contentType); attachment.setSize((int)status.getFileSize() ); attachment.setInputStream(inputStream); attachment.setName(status.getFileName()); setObjectTypeAndObjectId(attachment, objectType, objectId); } else { attachment = attachmentService.createAttachment(objectType, objectId, status.getFileName(), contentType, inputStream, (int) status.getFileSize()); } User user = SecurityHelper.getUser(); attachment.setUser(user); attachmentService.saveAttachment(attachment); if (link & !isUpdate) { sharedLinkService.getSharedLink(Models.ATTACHMENT.getObjectType(), attachment.getAttachmentId(), true); } } private void setObjectTypeAndObjectId(Attachment attachment, int objectType, long objectId) { if (attachment instanceof LocalAttachment){ ((LocalAttachment) attachment).setObjectType(objectType); ((LocalAttachment) attachment).setObjectId(objectId); }else{ ((DefaultAttachment) attachment).setObjectType(objectType); ((DefaultAttachment) attachment).setObjectId(objectId); } } /** * Create a new upload for tus protocol * * @param attachmentId * @param fileSize * @param uploadMetadata * @return * @throws IOException */ @PostMapping("/{attachmentId:[\\p{Digit}]+}/tus") public ResponseEntity<?> createUpload( @PathVariable Long attachmentId, @RequestHeader(TusHttpHeader.UPLOAD_LENGTH) long fileSize, @RequestHeader(TusHttpHeader.UPLOAD_METADATA) String uploadMetadata) throws IOException { return handleCreationPostRequest(attachmentId, fileSize, uploadMetadata); } /** * Upload a file chunk for tus protocol * * @param attachmentId * @param encodedFileName * @param offset * @param tusVersion * @param data * @return * @throws IOException */ @PatchMapping("/{attachmentId:[\\p{Digit}]+}/tus/{encodedFileName}") public ResponseEntity<?> uploadFile(@PathVariable Long attachmentId, @PathVariable String encodedFileName, @RequestHeader(TusHttpHeader.UPLOAD_OFFSET) long offset, @RequestHeader(TusHttpHeader.TUS_RESUMABLE) String tusVersion, @RequestBody byte[] data) throws IOException { return handleCreationPatchRequest(encodedFileName, offset, tusVersion, data); } /** * Get the upload offset for the file * * @param attachmentId * @param encodedFileName * @return * @throws IOException */ @RequestMapping(value = "/{attachmentId:[\\p{Digit}]+}/tus/{encodedFileName}", method = RequestMethod.HEAD) public ResponseEntity<?> getFileUploadOffset( @PathVariable Long attachmentId, @PathVariable String encodedFileName) throws IOException { return handleCreationHeadRequest(encodedFileName); } }