1.前端h5
<!DOCTYPE html>
<html>
<head>
<title>Video Player</title>
</head>
<body>
<video id="videoPlayer" width="640" height="360" controls>
<source src="http://localhost:8085/video" type="">
</video>
</body>
</html>
2.后端
1.文件在本地
@RequestMapping(value = "/video", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<byte[]> getVideo(@RequestHeader(value = "Range", required = false) String rangeHeader) throws IOException {
File videoFile = new File("D:\\Download\\dolby-atmos-trailer_leaf_1080 (1).mp4");
HttpHeaders headers = new HttpHeaders();
long contentLength = videoFile.length();
headers.setContentLength(contentLength);
if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
String[] range = rangeHeader.substring("bytes=".length()).split("-");
long start = Long.parseLong(range[0]);
long end = range.length > 1 ? Long.parseLong(range[1]) : contentLength - 1;
long rangeLength = end - start + 1;
System.out.println("rangeHeader" + start + "----" + end);
System.out.println("rangeLength>>" + rangeLength);
RandomAccessFile randomAccessFile = new RandomAccessFile(videoFile, "r");
randomAccessFile.seek(start);
byte[] buffer = new byte[(int) rangeLength];
randomAccessFile.readFully(buffer);
headers.set("Content-Range", "bytes " + start + "-" + end + "/" + contentLength);
// headers.set("Accept-Ranges", "bytes");
System.out.println("Content-Range"+headers.get("Content-Range"));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<>(buffer, headers, HttpStatus.PARTIAL_CONTENT);
} else {
byte[] videoBytes = Files.readAllBytes(videoFile.toPath());
return new ResponseEntity<>(videoBytes, headers, HttpStatus.OK);
}
}
2.文件在远程(本地代理下)
@RequestMapping(value = "/getVideoDwn", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void getVideoDwn(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 视频文件的网络地址
String videoUrl = "https://cn-beijing-data.aliyundrive.net/5fc0c8b4f1f50595b5094497b75fea8afe7b715e%2F5fc0c8b405587a69f8254396abeec229a33223ac?di=bj29&dr=34609702&f=6403623a11cebf9d430142cf99e4898d46ec77ef&response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27dolby-atmos-trailer_leaf_1080.mp4&security-token=CAIS%2BgF1q6Ft5B2yfSjIr5aNDoLStLIZ%2F7jfWBf9sTcGZsJhtbXupzz2IHFPeHJrBeAYt%2FoxmW1X5vwSlq5rR4QAXlDfNUugGA%2FTqVHPWZHInuDox55m4cTXNAr%2BIhr%2F29CoEIedZdjBe%2FCrRknZnytou9XTfimjWFrXWv%2Fgy%2BQQDLItUxK%2FcCBNCfpPOwJms7V6D3bKMuu3OROY6Qi5TmgQ41Uh1jgjtPzkkpfFtkGF1GeXkLFF%2B97DRbG%2FdNRpMZtFVNO44fd7bKKp0lQLukMWr%2Fwq3PIdp2ma447NWQlLnzyCMvvJ9OVDFyN0aKEnH7J%2Bq%2FzxhTPrMnpkSlacGoABKubZYG1xUq2lZMDjFlGRHUhz9UGR2xV3W9k%2Bnart0MJdTOPerzUFy16thRkU6GG0Yfn4CLH3Mat3IgbUVN%2FKIe%2F7Zwv4ZWsaqEX%2BaK1YAHbsMO2676F1uBcsoJQ9RB0ILokFBdp8je4vNp7w8bgz9HU%2FKAkticmNtIX8tkSUtGI%3D&u=254808010963075794&x-oss-access-key-id=STS.NU8E8fYm8Hz4Z1LU7SjMMZpEE&x-oss-expires=1678377242&x-oss-signature=ZF9JWAFQb%2F06KiV5hhIM1A4NP5GvZvs9NbhChblpTKc%3D&x-oss-signature-version=OSS2";
HttpURLConnection connection = (HttpURLConnection) new URL(videoUrl).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Referer", "https://www.aliyundrive.com/");
long contentLength = connection.getContentLengthLong();
// response.setHeader("Content-Type", "video/mp4");
// response.setHeader("Content-Length", String.valueOf(contentLength));
String rangeHeader = request.getHeader("Range");
if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
String[] range = rangeHeader.substring("bytes=".length()).split("-");
long start = Long.parseLong(range[0]);
long end = range.length > 1 ? Long.parseLong(range[1]) : contentLength - 1;
long rangeLength = end - start + 1;
System.out.println("rangeHeader" + start + "-" + end);
System.out.println("rangeLength>>" + rangeLength);
HttpURLConnection connection1 = (HttpURLConnection) new URL(videoUrl).openConnection();
//connection1.setRequestMethod("GET");
connection1.setRequestProperty("Referer", "https://www.aliyundrive.com/");
//connection.setRequestProperty("Referer", "https://www.aliyundrive.com/");
connection1.setRequestProperty("Range", "bytes=" + start + "-" + end);
InputStream inputStream = connection1.getInputStream();
byte[] buffer = new byte[1024];
int len = -1;
response.setStatus(206);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
response.addHeader("Content-Range", "bytes " + start + "-" + end + "/" + contentLength);
while ((len = inputStream.read(buffer)) != -1) {
response.getOutputStream().write(buffer, 0, len);
}
inputStream.close();
response.getOutputStream().close();
connection.disconnect();
connection1.disconnect();
} else {
InputStream inputStream = connection.getInputStream();
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
inputStream.close();
outputStream.close();
}
}
多线程下载加速(支持断点)
@RequestMapping(value = "/videoManyThread", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void getVideoManyThread(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
// 视频文件的网络地址
String videoUrl = "https://cn-beijing-data.aliyundrive.net/wPA9FhRu%2F292012%2F63baa96ffffd146b8fa14608996c9870234550d9%2F63baa96f78a17f56b2884e58b71d91f22754f7ac?callback=eyJjYWxsYmFja1VybCI6Imh0dHA6Ly9wZHNhcGkuYWxpeXVuZHJpdmUuY29tL3YyL2ZpbGUvZG93bmxvYWRfY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJodHRwSGVhZGVyLnJhbmdlPSR7aHR0cEhlYWRlci5yYW5nZX1cdTAwMjZidWNrZXQ9JHtidWNrZXR9XHUwMDI2b2JqZWN0PSR7b2JqZWN0fVx1MDAyNmRvbWFpbl9pZD0ke3g6ZG9tYWluX2lkfVx1MDAyNnVzZXJfaWQ9JHt4OnVzZXJfaWR9XHUwMDI2ZHJpdmVfaWQ9JHt4OmRyaXZlX2lkfVx1MDAyNmZpbGVfaWQ9JHt4OmZpbGVfaWR9IiwiY2FsbGJhY2tCb2R5VHlwZSI6ImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSJ9&callback-var=eyJ4OmRvbWFpbl9pZCI6ImJqMjkiLCJ4OnVzZXJfaWQiOiI3NGQ2NzQ4M2M5MWU0NzViYmJhZjc0YmQyMmUyNTUxZSIsIng6ZHJpdmVfaWQiOiIzNDYwOTcwMiIsIng6ZmlsZV9pZCI6IjYzZWQ5NTVmZGZmM2NhOWJhNTQ4NDJiMWEzNzdjMzVjMGFmM2E0NzgifQ%3D%3D&di=bj29&dr=34609702&f=63ed955fdff3ca9ba54842b1a377c35c0af3a478&response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27ZYJFQ.S01E18.2023.1080P.H264.AAC-YYDS.mp4&security-token=CAIS%2BgF1q6Ft5B2yfSjIr5DEGs3OmJVv37XeY0KDvWoZWrZpgPDtgTz2IHFPeHJrBeAYt%2FoxmW1X5vwSlq5rR4QAXlDfNVjdCnPSqVHPWZHInuDox55m4cTXNAr%2BIhr%2F29CoEIedZdjBe%2FCrRknZnytou9XTfimjWFrXWv%2Fgy%2BQQDLItUxK%2FcCBNCfpPOwJms7V6D3bKMuu3OROY6Qi5TmgQ41Uh1jgjtPzkkpfFtkGF1GeXkLFF%2B97DRbG%2FdNRpMZtFVNO44fd7bKKp0lQLukMWr%2Fwq3PIdp2ma447NWQlLnzyCMvvJ9OVDFyN0aKEnH7J%2Bq%2FzxhTPrMnpkSlacGoABfVnVHirOkxNrRMWIp45pNdFGEzh4fe1XnvKfIGLM%2BX740%2Fh%2BM8bnTOnoluAbU%2F%2FSzHzadNYgzea2Bhd63vwgofZmIi7tCMbvtsa4f2fM%2FZ8%2FdAXcLc5I0YJQkqP8bBSL8LqZhh4%2FgJJ5YyqmSoLYSJDSOfmEBNF6V6V%2FYUpYvek%3D&u=74d67483c91e475bbbaf74bd22e2551e&x-oss-access-key-id=STS.NSqQwzuJNhw5ad2YjLV9Eo5Fc&x-oss-additional-headers=referer&x-oss-expires=1678448406&x-oss-signature=bEAvAJEFH3MxsZUVT0Vqv%2BoXLBSHaVbWcYsa8aFXFh8%3D&x-oss-signature-version=OSS2";
//视频时间秒
long videoTime = 2580L;
HttpURLConnection connection = (HttpURLConnection) new URL(videoUrl).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Referer", "https://www.aliyundrive.com/");
//62072131
long contentLength = connection.getContentLengthLong();
long videoLength = contentLength;
// response.setHeader("Content-Type", "video/mp4");
// response.setHeader("Content-Length", String.valueOf(contentLength));
String rangeHeader = request.getHeader("Range");
if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
String[] range = rangeHeader.substring("bytes=".length()).split("-");
long start = Long.parseLong(range[0]);
contentLength = contentLength / videoTime * 5 + start;
long end = range.length > 1 ? Long.parseLong(range[1]) : contentLength - 1;
if (end > videoLength) {
end = videoLength-1;
}
long rangeLength = end - start + 1;
System.out.println("rangeHeader" + start + "-" + end);
System.out.println("rangeLength>>" + rangeLength);
List<MultiThreadDownloader1.DownloadThread> dwnResult = MultiThreadDownloader1.dwn(videoUrl, rangeLength, start, 16);
//HttpURLConnection connection1 = (HttpURLConnection) new URL(videoUrl).openConnection();
//connection1.setRequestMethod("GET");
// connection1.setRequestProperty("Referer", "https://www.aliyundrive.com/");
// //connection.setRequestProperty("Referer", "https://www.aliyundrive.com/");
// connection1.setRequestProperty("Range", "bytes=" + start + "-" + end);
// InputStream inputStream = connection1.getInputStream();
//
// byte[] buffer = new byte[1024];
// int len;
response.setStatus(206);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
response.addHeader("Content-Range", "bytes " + start + "-" + end + "/" + videoLength);
for (MultiThreadDownloader1.DownloadThread downloadThread : dwnResult) {
response.getOutputStream().write(downloadThread.getData(), 0, downloadThread.getData().length);
}
//inputStream.close();
response.getOutputStream().close();
connection.disconnect();
//connection1.disconnect();
} else {
InputStream inputStream = connection.getInputStream();
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
inputStream.close();
outputStream.close();
}
}
public class MultiThreadDownloader1 {
private static final String DOWNLOAD_URL = "https://cn-beijing-data.aliyundrive.net/5fc0c8b4f1f50595b5094497b75fea8afe7b715e%2F5fc0c8b405587a69f8254396abeec229a33223ac?di=bj29&dr=34609702&f=6403623a11cebf9d430142cf99e4898d46ec77ef&response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27dolby-atmos-trailer_leaf_1080.mp4&security-token=CAIS%2BgF1q6Ft5B2yfSjIr5fUINHDmbZ2zYi%2FNWPVkHoFaLxO25%2FZhzz2IHFPeHJrBeAYt%2FoxmW1X5vwSlq5rR4QAXlDfNXKYFkrTqVHPWZHInuDox55m4cTXNAr%2BIhr%2F29CoEIedZdjBe%2FCrRknZnytou9XTfimjWFrXWv%2Fgy%2BQQDLItUxK%2FcCBNCfpPOwJms7V6D3bKMuu3OROY6Qi5TmgQ41Uh1jgjtPzkkpfFtkGF1GeXkLFF%2B97DRbG%2FdNRpMZtFVNO44fd7bKKp0lQLukMWr%2Fwq3PIdp2ma447NWQlLnzyCMvvJ9OVDFyN0aKEnH7J%2Bq%2FzxhTPrMnpkSlacGoABg%2F8a2EeaNy%2FX0vUV5PxFFvCCQNK0HaXpQFXRgW8SXxbgenaJNdtzK4BDYNsAKrH1x%2FE8NMf3qatXM7QXvRB6DCjZ6hQoqEhsYSha9oUnsVdV%2F1dVgACHN5iLi9smoZJ5h4sHEP%2B97cs%2F9NlTwLC1%2Bg4%2Fo49KTxqkIduEtUaDw94%3D&u=254808010963075794&x-oss-access-key-id=STS.NTakkwtiWzJT7EdtzPd3b4Zre&x-oss-expires=1678247687&x-oss-signature=gXQa9IYNHVFYH%2FXrf%2B8U%2BZlCmir%2B0GQ363tMTdekcVs%3D&x-oss-signature-version=OSS2";
//private static final int THREAD_COUNT = 2;
public static void main(String[] args) {
try {
//dwn();
} catch (Exception e) {
e.printStackTrace();
}
}
public static List<DownloadThread> dwn(String dwnUrl, long totalLength, long chushistartIndex,int THREAD_COUNT) throws IOException, InterruptedException {
long startTime = System.currentTimeMillis();
System.out.println("开始下载");
URL url = new URL(dwnUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Referer", "https://www.aliyundrive.com/");
List<DownloadThread> threads = new ArrayList<>();
long blockSize = totalLength / THREAD_COUNT;
for (long i = 0; i < THREAD_COUNT; i++) {
long startIndex = i * blockSize + chushistartIndex;
long endIndex = (i + 1) * blockSize + +chushistartIndex - 1;
if (i == THREAD_COUNT - 1) {
endIndex = totalLength + +chushistartIndex - 1;
}
DownloadThread thread = new DownloadThread(dwnUrl, startIndex, endIndex);
threads.add(thread);
thread.start();
}
boolean finished = false;
while (!finished) {
finished = true;
for (DownloadThread thread : threads) {
if (!thread.isFinished()) {
finished = false;
break;
}
}
Thread.sleep(100);
}
// File file = new File("D:\\Download\\file.mp4");
// FileOutputStream outputStream = new FileOutputStream(file);
// for (DownloadThread thread : threads) {
// if (thread.getData() != null)
// outputStream.write(thread.getData());
// }
//outputStream.close();
System.out.println((System.currentTimeMillis() - startTime) / 1000.0);
return threads;
}
public static class DownloadThread extends Thread {
private String url;
private long startIndex;
private long endIndex;
private boolean finished;
private byte[] data;
public DownloadThread(String url, long startIndex, long endIndex) {
this.url = url;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.finished = false;
}
public boolean isFinished() {
return finished;
}
public byte[] getData() {
return data;
}
@Override
public void run() {
try {
URL url = new URL(this.url);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Referer", "https://www.aliyundrive.com/");
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
InputStream inputStream = conn.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
inputStream.close();
outputStream.close();
data = outputStream.toByteArray();
finished = true;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}