feat(media): 支持后台转码配置与缩略图轴
This commit is contained in:
1 parent
70da939a58
commit
316baf28d6
39 files changed
+1523
-38
No files matched your search
+22
@@ -5,7 +5,10 @@ package com.fruitshorts.admin.controller;
|
||||
import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import com.fruitshorts.framework.security.ImpersonationGuard;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.media.config.MediaTranscodeProfile;
|
||||
import com.fruitshorts.media.service.MediaService;
|
||||
import com.fruitshorts.media.service.MediaTranscodeProfileService;
|
||||
import com.fruitshorts.media.vo.MediaAssetRespVO;
|
||||
import com.fruitshorts.media.vo.UploadCompleteReqVO;
|
||||
import com.fruitshorts.media.vo.UploadInitReqVO;
|
||||
@@ -19,6 +22,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -35,6 +39,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
public class MediaController {
|
||||
|
||||
private final MediaService mediaService;
|
||||
private final MediaTranscodeProfileService profileService;
|
||||
|
||||
@Operation(summary = "初始化分片上传")
|
||||
@PostMapping("/upload/init")
|
||||
@@ -78,4 +83,21 @@ public class MediaController {
|
||||
public Result<MediaAssetRespVO> get(@PathVariable Long id) {
|
||||
return Result.ok(mediaService.get(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "读取转码档位配置")
|
||||
@GetMapping("/transcode-profile")
|
||||
@PreAuthorize("@ss.hasPermission('episode:upload')")
|
||||
public Result<MediaTranscodeProfile> transcodeProfile() {
|
||||
return Result.ok(profileService.readConfiguredProfile());
|
||||
}
|
||||
|
||||
@Operation(summary = "保存转码档位配置")
|
||||
@PutMapping("/transcode-profile")
|
||||
@PreAuthorize("@ss.hasPermission('episode:upload')")
|
||||
@OperationLog(module = "后台管理", action = "修改转码设置")
|
||||
public Result<MediaTranscodeProfile> saveTranscodeProfile(
|
||||
@Valid @RequestBody MediaTranscodeProfile profile) {
|
||||
ImpersonationGuard.rejectWrite();
|
||||
return Result.ok(profileService.save(profile));
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
package com.fruitshorts.admin.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fruitshorts.admin.support.ControllerContractSupport;
|
||||
import com.fruitshorts.media.config.MediaTranscodeProfile;
|
||||
import com.fruitshorts.media.config.TranscodeProperties;
|
||||
import com.fruitshorts.media.service.MediaService;
|
||||
import com.fruitshorts.media.service.MediaTranscodeProfileService;
|
||||
import com.fruitshorts.system.service.ConfigService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* 后台转码配置接口:默认值、非法拒绝与成功落库。
|
||||
*/
|
||||
class MediaTranscodeProfileContractTest {
|
||||
|
||||
private ConfigService configService;
|
||||
private ObjectMapper objectMapper;
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
configService = mock(ConfigService.class);
|
||||
objectMapper = new ObjectMapper();
|
||||
MediaTranscodeProfileService profileService = new MediaTranscodeProfileService(
|
||||
configService, objectMapper, new TranscodeProperties());
|
||||
MediaController controller = new MediaController(mock(MediaService.class), profileService);
|
||||
mockMvc = ControllerContractSupport.mockMvcOf(controller);
|
||||
given(configService.get(eq(MediaTranscodeProfileService.CONFIG_KEY), anyString()))
|
||||
.willReturn("");
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_return_default_profile_when_config_is_missing() throws Exception {
|
||||
mockMvc.perform(get("/admin/media/transcode-profile"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.segmentSeconds").value(6))
|
||||
.andExpect(jsonPath("$.data.ladder.length()").value(4))
|
||||
.andExpect(jsonPath("$.data.ladder[0].quality").value("360p"))
|
||||
.andExpect(jsonPath("$.data.sprite.columns").value(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_reject_illegal_profile_without_writing_config() throws Exception {
|
||||
MediaTranscodeProfile profile = new MediaTranscodeProfile();
|
||||
profile.getLadder().get(0).setWidth(641);
|
||||
|
||||
mockMvc.perform(put("/admin/media/transcode-profile")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(profile)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(400))
|
||||
.andExpect(jsonPath("$.message").value("宽高必须为正偶数"));
|
||||
|
||||
verify(configService, never()).update(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_persist_profile_when_request_is_valid() throws Exception {
|
||||
MediaTranscodeProfile profile = new MediaTranscodeProfile();
|
||||
profile.setSegmentSeconds(4);
|
||||
|
||||
mockMvc.perform(put("/admin/media/transcode-profile")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(profile)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.segmentSeconds").value(4));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<Map<String, String>> captor = ArgumentCaptor.forClass(Map.class);
|
||||
verify(configService).update(captor.capture());
|
||||
assertThat(captor.getValue().get(MediaTranscodeProfileService.CONFIG_KEY))
|
||||
.contains("\"segmentSeconds\":4");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user