From 7666446ed83c837e1f1f440cc74e06f75429e7ee Mon Sep 17 00:00:00 2001 From: shikong <919411476@qq.com> Date: Fri, 8 Sep 2023 16:33:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wvp/api/download/DownloadController.java | 37 ++++++++ .../wvp/api/video/VideoController.java | 10 ++- gb28181-wvp-proxy-service/pom.xml | 9 ++ .../wvp/service/download/DownloadService.java | 88 +++++++++++++++++++ .../src/main/resources/application.yaml | 5 -- .../src/main/resources/application.yml | 43 +++++++++ .../gb28181/wvp/test/WvpProxyTest.java | 37 +++++++- .../src/main/resources/application-local.yml | 1 + 8 files changed, 217 insertions(+), 13 deletions(-) create mode 100644 gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/download/DownloadController.java create mode 100644 gb28181-wvp-proxy-service/src/main/java/cn/skcks/docking/gb28181/wvp/service/download/DownloadService.java delete mode 100644 gb28181-wvp-proxy-service/src/main/resources/application.yaml create mode 100644 gb28181-wvp-proxy-service/src/main/resources/application.yml diff --git a/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/download/DownloadController.java b/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/download/DownloadController.java new file mode 100644 index 0000000..ea712c6 --- /dev/null +++ b/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/download/DownloadController.java @@ -0,0 +1,37 @@ +package cn.skcks.docking.gb28181.wvp.api.download; + +import cn.skcks.docking.gb28181.wvp.config.SwaggerConfig; +import cn.skcks.docking.gb28181.wvp.service.download.DownloadService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.web.bind.annotation.*; + +@RequiredArgsConstructor +@Tag(name = "下载") +@RestController +@RequestMapping("/download") +public class DownloadController { + private final DownloadService downloadService; + + @Bean + public GroupedOpenApi downloadApi() { + return SwaggerConfig.api("DownloadApi", "/download"); + } + + @Operation(summary = "下载代理") + @RequestMapping(method = RequestMethod.HEAD, value = "/proxy") + public void downloadProxyHeader(HttpServletRequest request, HttpServletResponse response, @RequestParam String url) { + downloadService.header(request, response, url); + } + + @Operation(summary = "下载代理") + @GetMapping("/proxy") + public void downloadProxy(HttpServletRequest request, HttpServletResponse response, @RequestParam String url) { + downloadService.download(request, response, url); + } +} diff --git a/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/video/VideoController.java b/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/video/VideoController.java index 2444c00..aff32f2 100644 --- a/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/video/VideoController.java +++ b/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/video/VideoController.java @@ -2,6 +2,7 @@ package cn.skcks.docking.gb28181.wvp.api.video; import cn.skcks.docking.gb28181.media.config.ZlmMediaConfig; import cn.skcks.docking.gb28181.wvp.config.SwaggerConfig; +import cn.skcks.docking.gb28181.wvp.service.download.DownloadService; import cn.skcks.docking.gb28181.wvp.service.video.RecordService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -9,7 +10,6 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.springdoc.core.models.GroupedOpenApi; import org.springframework.context.annotation.Bean; import org.springframework.http.MediaType; @@ -26,6 +26,7 @@ import org.springframework.web.bind.annotation.ResponseBody; public class VideoController { private final ZlmMediaConfig config; private final RecordService recordService; + private final DownloadService downloadService; @Bean public GroupedOpenApi videoApi() { @@ -36,8 +37,9 @@ public class VideoController { @GetMapping(produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) @ResponseBody public void video(HttpServletRequest request, HttpServletResponse response) { - String url = StringUtils.joinWith("/", config.getUrl(), "live", "test.live.flv"); - log.info("url {}", url); - recordService.record(request,response,url,15); +// String url = StringUtils.joinWith("/", config.getUrl(), "live", "test.live.flv"); +// log.info("url {}", url); +// recordService.record(request,response,url,15); + downloadService.download(request,response,"http://192.168.1.241:18979/download/recordTemp/0490d767d94ce20aedce57c862b6bfe9/rtp/59777645.mp4"); } } diff --git a/gb28181-wvp-proxy-service/pom.xml b/gb28181-wvp-proxy-service/pom.xml index 84e8fdb..e60eb0b 100644 --- a/gb28181-wvp-proxy-service/pom.xml +++ b/gb28181-wvp-proxy-service/pom.xml @@ -168,6 +168,15 @@ + + + org.apache.httpcomponents.client5 + httpclient5 + + + io.github.openfeign + feign-httpclient + diff --git a/gb28181-wvp-proxy-service/src/main/java/cn/skcks/docking/gb28181/wvp/service/download/DownloadService.java b/gb28181-wvp-proxy-service/src/main/java/cn/skcks/docking/gb28181/wvp/service/download/DownloadService.java new file mode 100644 index 0000000..3162ea8 --- /dev/null +++ b/gb28181-wvp-proxy-service/src/main/java/cn/skcks/docking/gb28181/wvp/service/download/DownloadService.java @@ -0,0 +1,88 @@ +package cn.skcks.docking.gb28181.wvp.service.download; + +import cn.hutool.core.io.IoUtil; +import jakarta.servlet.AsyncContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpHead; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.springframework.stereotype.Service; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Optional; + +@Slf4j +@Service +public class DownloadService { + @SneakyThrows + public void header(HttpServletRequest request, HttpServletResponse response, String url) { + AsyncContext asyncContext = request.startAsync(); + asyncContext.setTimeout(0); + asyncContext.start(() -> { + try { + response.setHeader("Accept-Ranges", "none"); + response.setHeader("Connection", "close"); + header((HttpServletResponse) asyncContext.getResponse(), url); + } finally { + log.info("record 结束"); + asyncContext.complete(); + } + }); + } + + @SneakyThrows + private void header(HttpServletResponse response, String url) { + try (CloseableHttpClient client = HttpClients.custom().build()) { + HttpHead httpHead = new HttpHead(url); + client.execute(httpHead, resp -> { + setHeaderFromProxy(resp,response); + return null; + }); + } + } + + @SneakyThrows + private void setHeaderFromProxy(ClassicHttpResponse resp, HttpServletResponse response){ + response.setContentType(resp.getEntity().getContentType()); + Optional.ofNullable(resp.getHeader("Content-Disposition")).ifPresent((header)->{ + response.setHeader(header.getName(), header.getValue()); + }); + } + + @SneakyThrows + public void download(HttpServletRequest request, HttpServletResponse response, String url) { + AsyncContext asyncContext = request.startAsync(); + asyncContext.setTimeout(0); + asyncContext.start(() -> { + try { + response.setHeader("Accept-Ranges", "none"); + response.setHeader("Connection", "close"); + download((HttpServletResponse) asyncContext.getResponse(), url); + } finally { + log.info("record 结束"); + asyncContext.complete(); + } + }); + } + + @SneakyThrows + private void download(HttpServletResponse response, String url) { + OutputStream outputStream = response.getOutputStream(); + + try (CloseableHttpClient client = HttpClients.custom().build()) { + HttpGet httpGet = new HttpGet(url); + client.execute(httpGet, resp -> { + setHeaderFromProxy(resp,response); + InputStream stream = resp.getEntity().getContent(); + IoUtil.copy(stream, outputStream); + return stream; + }); + } + } +} diff --git a/gb28181-wvp-proxy-service/src/main/resources/application.yaml b/gb28181-wvp-proxy-service/src/main/resources/application.yaml deleted file mode 100644 index 26dfe71..0000000 --- a/gb28181-wvp-proxy-service/src/main/resources/application.yaml +++ /dev/null @@ -1,5 +0,0 @@ -proxy: - wvp: - url: http://192.168.3.13:18978 - user: admin - passwd: admin \ No newline at end of file diff --git a/gb28181-wvp-proxy-service/src/main/resources/application.yml b/gb28181-wvp-proxy-service/src/main/resources/application.yml new file mode 100644 index 0000000..5ea5ca7 --- /dev/null +++ b/gb28181-wvp-proxy-service/src/main/resources/application.yml @@ -0,0 +1,43 @@ +server: + port: 18186 + +spring: + data: + redis: + # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1 + # host: 192.168.1.241 + host: 10.10.10.200 + # [必须修改] 端口号 + port: 16379 + # [可选] 数据库 DB + database: 15 + # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 + password: 12341234 + # [可选] 超时时间 + timeout: 10000 + datasource: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: 12341234 + url: jdbc:mysql://10.10.10.200:3306/gb28181_docking_platform?createDatabaseIfNotExist=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai + cloud: + openfeign: + httpclient: + connection-timeout: 0 + ok-http: + read-timeout: 0 + +media: + ip: 10.10.10.200 + url: 'http://10.10.10.200:5080' + # url: 'http://10.10.10.200:12580/anything/' + id: amrWMKmbKqoBjRQ9 +# secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc + secret: 4155cca6-2f9f-11ee-85e6-8de4ce2e7333 + +proxy: + wvp: + url: http://192.168.3.13:18978 + user: admin + passwd: admin diff --git a/gb28181-wvp-proxy-service/src/test/java/cn/skcks/docking/gb28181/wvp/test/WvpProxyTest.java b/gb28181-wvp-proxy-service/src/test/java/cn/skcks/docking/gb28181/wvp/test/WvpProxyTest.java index 616f219..bc8af4b 100644 --- a/gb28181-wvp-proxy-service/src/test/java/cn/skcks/docking/gb28181/wvp/test/WvpProxyTest.java +++ b/gb28181-wvp-proxy-service/src/test/java/cn/skcks/docking/gb28181/wvp/test/WvpProxyTest.java @@ -1,7 +1,9 @@ package cn.skcks.docking.gb28181.wvp.test; +import cn.hutool.core.io.IoUtil; import cn.hutool.crypto.digest.MD5; import cn.skcks.docking.gb28181.common.json.JsonResponse; +import cn.skcks.docking.gb28181.wvp.WvpProxyTestApplication; import cn.skcks.docking.gb28181.wvp.config.WvpProxyConfig; import cn.skcks.docking.gb28181.wvp.dto.device.GetDeviceChannelsReq; import cn.skcks.docking.gb28181.wvp.dto.device.GetDeviceChannelsResp; @@ -11,17 +13,24 @@ import cn.skcks.docking.gb28181.wvp.dto.login.WvpLoginReq; import cn.skcks.docking.gb28181.wvp.dto.login.WvpLoginResp; import cn.skcks.docking.gb28181.wvp.proxy.WvpProxyClient; import lombok.extern.slf4j.Slf4j; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.io.CloseMode; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit.jupiter.SpringExtension; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Paths; + @Slf4j -@SpringBootTest -@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) +@SpringBootTest(classes = WvpProxyTestApplication.class) @ExtendWith(SpringExtension.class) public class WvpProxyTest { @Autowired @@ -55,4 +64,24 @@ public class WvpProxyTest { log.info("{}", item); }); } + + @Test + void downloadTest() throws IOException { + final CloseableHttpClient client = HttpClients.custom() + .build(); + + String tmpDir = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath(); + File file = new File(Paths.get(tmpDir,"test.mp4").toUri()); + log.info("临时文件 路径 => {}",file.getAbsolutePath()); + FileOutputStream outputStream = new FileOutputStream(file); + + String url = "http://192.168.1.241:18979/download/recordTemp/0490d767d94ce20aedce57c862b6bfe9/rtp/59777645.mp4"; + HttpGet httpGet = new HttpGet(url); + client.execute(httpGet, response -> { + InputStream stream = response.getEntity().getContent(); + IoUtil.copy(stream,outputStream); + return stream; + }); + client.close(CloseMode.GRACEFUL); + } } diff --git a/gb28181-wvp-proxy-starter/src/main/resources/application-local.yml b/gb28181-wvp-proxy-starter/src/main/resources/application-local.yml index b8215c9..d0ba8ba 100644 --- a/gb28181-wvp-proxy-starter/src/main/resources/application-local.yml +++ b/gb28181-wvp-proxy-starter/src/main/resources/application-local.yml @@ -32,6 +32,7 @@ spring: connection-timeout: 0 ok-http: read-timeout: 0 + media: ip: 10.10.10.200 url: 'http://10.10.10.200:5080'