下载代理

This commit is contained in:
shikong 2023-09-08 16:33:53 +08:00
parent 0a7fefaead
commit 7666446ed8
8 changed files with 217 additions and 13 deletions

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -168,6 +168,15 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -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;
});
}
}
}

View File

@ -1,5 +0,0 @@
proxy:
wvp:
url: http://192.168.3.13:18978
user: admin
passwd: admin

View File

@ -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

View File

@ -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);
}
}

View File

@ -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'