This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package ru.soune.nocopy.controller;
|
package ru.soune.nocopy.controller;
|
||||||
|
|
||||||
|
import com.google.api.client.util.IOUtils;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
import com.vrt.NoCopyFileService;
|
import com.vrt.NoCopyFileService;
|
||||||
import com.vrt.fileprotection.FileProtector;
|
import com.vrt.fileprotection.FileProtector;
|
||||||
import com.vrt.fileprotection.NoCopyCheckResult;
|
import com.vrt.fileprotection.NoCopyCheckResult;
|
||||||
@@ -13,12 +15,15 @@ import org.springframework.data.domain.Page;
|
|||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.web.PageableDefault;
|
import org.springframework.data.web.PageableDefault;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.validation.FieldError;
|
import org.springframework.validation.FieldError;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
import ru.soune.nocopy.dto.BaseRequest;
|
import ru.soune.nocopy.dto.BaseRequest;
|
||||||
import ru.soune.nocopy.dto.BaseResponse;
|
import ru.soune.nocopy.dto.BaseResponse;
|
||||||
import ru.soune.nocopy.dto.MessageCode;
|
import ru.soune.nocopy.dto.MessageCode;
|
||||||
@@ -43,6 +48,7 @@ import ru.soune.nocopy.service.file.cloud.CloudStorageService;
|
|||||||
import ru.soune.nocopy.service.register.AuthService;
|
import ru.soune.nocopy.service.register.AuthService;
|
||||||
import ru.soune.nocopy.service.user.moderation.UserVerificationService;
|
import ru.soune.nocopy.service.user.moderation.UserVerificationService;
|
||||||
import ru.soune.nocopy.util.FileUtil;
|
import ru.soune.nocopy.util.FileUtil;
|
||||||
|
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -508,8 +514,6 @@ public class ApiController {
|
|||||||
// errorData));
|
// errorData));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
InputStream stream = cloudStorageService.readFileFromStorage(entityResponse.getProtectedFilePath());
|
|
||||||
|
|
||||||
// if (!file.exists()) {
|
// if (!file.exists()) {
|
||||||
// Map<String, Object> errorData = new HashMap<>();
|
// Map<String, Object> errorData = new HashMap<>();
|
||||||
// errorData.put("file", file.exists());
|
// errorData.put("file", file.exists());
|
||||||
@@ -520,11 +524,19 @@ public class ApiController {
|
|||||||
// errorData));
|
// errorData));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
StreamingResponseBody responseBody = outputStream -> {
|
||||||
|
try (InputStream stream = cloudStorageService.readFileFromStorage(entityResponse.getProtectedFilePath())) {
|
||||||
|
ByteStreams.copy(stream, outputStream);
|
||||||
|
} catch (NoSuchKeyException e) {
|
||||||
|
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "File not found");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||||
"attachment; filename=\"" + entityResponse.getFileName() + "\"")
|
"attachment; filename=\"" + entityResponse.getFileName() + "\"")
|
||||||
.body(new InputStreamResource(stream));
|
.body(responseBody);
|
||||||
} catch (FileEntityNotFoundException e) {
|
} catch (FileEntityNotFoundException e) {
|
||||||
Map<String, Object> errorData = new HashMap<>();
|
Map<String, Object> errorData = new HashMap<>();
|
||||||
errorData.put("fileId", fileId);
|
errorData.put("fileId", fileId);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package ru.soune.nocopy.controller;
|
package ru.soune.nocopy.controller;
|
||||||
|
|
||||||
|
import com.google.api.client.util.IOUtils;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
import com.vrt.NoCopyFileService;
|
import com.vrt.NoCopyFileService;
|
||||||
import com.vrt.fileprotection.FileProtector;
|
import com.vrt.fileprotection.FileProtector;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -8,6 +10,7 @@ import org.springframework.core.io.InputStreamResource;
|
|||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.*;
|
import org.springframework.http.*;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
import ru.soune.nocopy.dto.file.CheckStatus;
|
import ru.soune.nocopy.dto.file.CheckStatus;
|
||||||
import ru.soune.nocopy.entity.file.FileEntity;
|
import ru.soune.nocopy.entity.file.FileEntity;
|
||||||
import ru.soune.nocopy.entity.file.ProtectionStatus;
|
import ru.soune.nocopy.entity.file.ProtectionStatus;
|
||||||
@@ -21,6 +24,7 @@ import ru.soune.nocopy.service.file.ImageResizeService;
|
|||||||
import ru.soune.nocopy.service.file.ZipService;
|
import ru.soune.nocopy.service.file.ZipService;
|
||||||
import ru.soune.nocopy.service.file.cloud.CloudStorageService;
|
import ru.soune.nocopy.service.file.cloud.CloudStorageService;
|
||||||
import ru.soune.nocopy.util.FileUtil;
|
import ru.soune.nocopy.util.FileUtil;
|
||||||
|
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
@@ -55,12 +59,10 @@ public class FileController {
|
|||||||
private CloudStorageService cloudStorageService;
|
private CloudStorageService cloudStorageService;
|
||||||
|
|
||||||
@GetMapping("/public/{fileId}")
|
@GetMapping("/public/{fileId}")
|
||||||
public ResponseEntity<InputStreamResource> getPublicFile(@PathVariable String fileId) {
|
public ResponseEntity<StreamingResponseBody> getPublicFile(@PathVariable String fileId) {
|
||||||
try {
|
try {
|
||||||
FileEntity fileEntity = fileRepository.findById(fileId)
|
FileEntity fileEntity = fileRepository.findById(fileId)
|
||||||
.orElseThrow(() -> new FileNotFoundException("Not found: " + fileId));
|
.orElseThrow(() -> new FileNotFoundException("Not found in DB: " + fileId));
|
||||||
|
|
||||||
InputStream inputStream = cloudStorageService.readFileFromStorage(fileEntity.getFilePath());
|
|
||||||
|
|
||||||
MediaType mediaType = getMediaType(fileEntity);
|
MediaType mediaType = getMediaType(fileEntity);
|
||||||
|
|
||||||
@@ -68,15 +70,26 @@ public class FileController {
|
|||||||
.filename(fileEntity.getOriginalFileName(), StandardCharsets.UTF_8)
|
.filename(fileEntity.getOriginalFileName(), StandardCharsets.UTF_8)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
StreamingResponseBody responseBody = outputStream -> {
|
||||||
|
try (InputStream inputStream = cloudStorageService.readFileFromStorage(fileEntity.getFilePath())) {
|
||||||
|
ByteStreams.copy(inputStream, outputStream);
|
||||||
|
} catch (NoSuchKeyException e) {
|
||||||
|
log.error("File disappeared from S3 during streaming: {}", fileId, e);
|
||||||
|
throw new IOException("File not found in storage", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.contentType(mediaType)
|
.contentType(mediaType)
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString())
|
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString())
|
||||||
.header(HttpHeaders.CACHE_CONTROL, "public, max-age=3600")
|
.header(HttpHeaders.CACHE_CONTROL, "public, max-age=3600")
|
||||||
.body(new InputStreamResource(inputStream));
|
.body(responseBody);
|
||||||
|
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
log.warn("File not found in DB: {}", fileId);
|
log.warn("File not found in DB: {}", fileId);
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
|
} catch (NoSuchKeyException e) {
|
||||||
|
log.warn("File not found in S3: {}", fileId);
|
||||||
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Error reading file: {}", fileId, e);
|
log.error("Error reading file: {}", fileId, e);
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||||
|
|||||||
Reference in New Issue
Block a user