Compare commits
3 Commits
master
...
d189578eda
| Author | SHA1 | Date | |
|---|---|---|---|
| d189578eda | |||
| 43f62fa6f1 | |||
| 1a3d341ace |
@@ -6,12 +6,16 @@ import com.ddf.vodsystem.controllers.dto.ClipUpdateRequest;
|
|||||||
import com.ddf.vodsystem.entities.Clip;
|
import com.ddf.vodsystem.entities.Clip;
|
||||||
import com.ddf.vodsystem.services.ClipService;
|
import com.ddf.vodsystem.services.ClipService;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.support.ResourceRegion;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpRange;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.MediaTypeFactory;
|
import org.springframework.http.MediaTypeFactory;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -78,19 +82,39 @@ public class ClipController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}/media")
|
@GetMapping("/{id}/media")
|
||||||
public ResponseEntity<Resource> downloadClip(@PathVariable Long id) {
|
public ResponseEntity<?> downloadClip(@PathVariable Long id, @RequestHeader HttpHeaders headers) throws IOException {
|
||||||
Resource resource = clipService.downloadClip(id);
|
Resource resource = clipService.downloadClip(id);
|
||||||
|
|
||||||
if (resource == null || !resource.exists()) {
|
if (resource == null || !resource.exists()) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<HttpRange> ranges = headers.getRange();
|
||||||
|
|
||||||
|
if (!ranges.isEmpty()) {
|
||||||
|
ResourceRegion region = createResourceRegion(resource, ranges.getFirst());
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
|
||||||
|
.header(HttpHeaders.ACCEPT_RANGES, "bytes")
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, String.format(FILENAME_HEADER, resource.getFilename()))
|
||||||
|
.contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
|
||||||
|
.body(region);
|
||||||
|
}
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
|
.header(HttpHeaders.ACCEPT_RANGES, "bytes")
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION, String.format(FILENAME_HEADER, resource.getFilename()))
|
.header(HttpHeaders.CONTENT_DISPOSITION, String.format(FILENAME_HEADER, resource.getFilename()))
|
||||||
.contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
|
.contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
|
||||||
.body(resource);
|
.body(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ResourceRegion createResourceRegion(Resource resource, HttpRange range) throws IOException {
|
||||||
|
long contentLength = resource.contentLength();
|
||||||
|
long start = range.getRangeStart(contentLength);
|
||||||
|
long end = range.getRangeEnd(contentLength);
|
||||||
|
return new ResourceRegion(resource, start, end - start + 1);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}/thumbnail")
|
@GetMapping("/{id}/thumbnail")
|
||||||
public ResponseEntity<Resource> downloadThumbnail(@PathVariable Long id) {
|
public ResponseEntity<Resource> downloadThumbnail(@PathVariable Long id) {
|
||||||
Resource resource = clipService.downloadThumbnail(id);
|
Resource resource = clipService.downloadThumbnail(id);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class MediaController {
|
|||||||
public ResponseEntity<APIResponse<UUIDResponse>> compress(
|
public ResponseEntity<APIResponse<UUIDResponse>> compress(
|
||||||
@RequestParam("file")MultipartFile file,
|
@RequestParam("file")MultipartFile file,
|
||||||
@Valid @ModelAttribute ClipOptions options
|
@Valid @ModelAttribute ClipOptions options
|
||||||
) throws IOException, InterruptedException {
|
) throws IOException {
|
||||||
Job job = mediaService.compress(file, options);
|
Job job = mediaService.compress(file, options);
|
||||||
return ResponseEntity.ok(new APIResponse<>(
|
return ResponseEntity.ok(new APIResponse<>(
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
|
|||||||
@@ -6,12 +6,16 @@ import com.ddf.vodsystem.dto.APIResponse;
|
|||||||
import com.ddf.vodsystem.entities.Vod;
|
import com.ddf.vodsystem.entities.Vod;
|
||||||
import com.ddf.vodsystem.services.VodService;
|
import com.ddf.vodsystem.services.VodService;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.support.ResourceRegion;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpRange;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.MediaTypeFactory;
|
import org.springframework.http.MediaTypeFactory;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -55,19 +59,39 @@ public class VodController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}/media")
|
@GetMapping("/{id}/media")
|
||||||
public ResponseEntity<Resource> downloadVod(@PathVariable Long id) {
|
public ResponseEntity<?> downloadVod(@PathVariable Long id, @RequestHeader HttpHeaders headers) throws IOException {
|
||||||
Resource resource = vodService.downloadVod(id);
|
Resource resource = vodService.downloadVod(id);
|
||||||
|
|
||||||
if (resource == null || !resource.exists()) {
|
if (resource == null || !resource.exists()) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<HttpRange> ranges = headers.getRange();
|
||||||
|
|
||||||
|
if (!ranges.isEmpty()) {
|
||||||
|
ResourceRegion region = createResourceRegion(resource, ranges.getFirst());
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
|
||||||
|
.header(HttpHeaders.ACCEPT_RANGES, "bytes")
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, String.format(FILENAME_HEADER, resource.getFilename()))
|
||||||
|
.contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
|
||||||
|
.body(region);
|
||||||
|
}
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
|
.header(HttpHeaders.ACCEPT_RANGES, "bytes")
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION, String.format(FILENAME_HEADER, resource.getFilename()))
|
.header(HttpHeaders.CONTENT_DISPOSITION, String.format(FILENAME_HEADER, resource.getFilename()))
|
||||||
.contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
|
.contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
|
||||||
.body(resource);
|
.body(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ResourceRegion createResourceRegion(Resource resource, HttpRange range) throws IOException {
|
||||||
|
long contentLength = resource.contentLength();
|
||||||
|
long start = range.getRangeStart(contentLength);
|
||||||
|
long end = range.getRangeEnd(contentLength);
|
||||||
|
return new ResourceRegion(resource, start, end - start + 1);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}/thumbnail")
|
@GetMapping("/{id}/thumbnail")
|
||||||
public ResponseEntity<Resource> downloadThumbnail(@PathVariable Long id) {
|
public ResponseEntity<Resource> downloadThumbnail(@PathVariable Long id) {
|
||||||
Resource resource = vodService.downloadThumbnail(id);
|
Resource resource = vodService.downloadThumbnail(id);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
|
|
||||||
@@ -129,11 +130,29 @@ public class DirectoryService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkDirPermissions() {
|
||||||
|
List<Path> dirs = List.of(
|
||||||
|
Path.of(tempInputsDir),
|
||||||
|
Path.of(tempOutputsDir),
|
||||||
|
Path.of(usersDir)
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Path> bad = dirs.stream()
|
||||||
|
.filter(p -> !Files.isDirectory(p) || !Files.isReadable(p) || !Files.isWritable(p))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (!bad.isEmpty()) {
|
||||||
|
throw new IllegalStateException("Unusable directories: " + bad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void createDirectoriesIfNotExist() throws IOException {
|
public void createDirectoriesIfNotExist() throws IOException {
|
||||||
Files.createDirectories(Path.of(tempInputsDir));
|
Files.createDirectories(Path.of(tempInputsDir));
|
||||||
Files.createDirectories(Path.of(tempOutputsDir));
|
Files.createDirectories(Path.of(tempOutputsDir));
|
||||||
Files.createDirectories(Path.of(usersDir));
|
Files.createDirectories(Path.of(usersDir));
|
||||||
|
|
||||||
|
checkDirPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(fixedRate = TEMP_DIR_CLEANUP_RATE)
|
@Scheduled(fixedRate = TEMP_DIR_CLEANUP_RATE)
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class MediaService {
|
|||||||
);
|
);
|
||||||
}).exceptionally(ex -> {
|
}).exceptionally(ex -> {
|
||||||
job.setState(JobState.FAILED);
|
job.setState(JobState.FAILED);
|
||||||
job.setErrorOutput(ex.getMessage());
|
job.setErrorOutput("Compression job failed");
|
||||||
logger.error("Compression job with UUID {} failed due to: {}", job.getUuid(), ex.getMessage());
|
logger.error("Compression job with UUID {} failed due to: {}", job.getUuid(), ex.getMessage());
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user