服务端可以用nginx,示例配置:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 8089;
server_name localhost;
location / {
root d:/video;
index index.html index.htm;
}
}
}
private static final int BUFFER_LENGTH = 1024 * 16;
private static final long EXPIRE_TIME = 1000 * 60 * 60 * 24;
private static final Pattern RANGE_PATTERN = Pattern.compile("bytes=(?<start>\\d*)-(?<end>\\d*)");
private static final File baseDir = new File("D:/video");
@RequestMapping(value = "resource")
public void resource(HttpSession session, String fileName,
HttpServletRequest request, HttpServletResponse response) throws IOException {
String realPath = baseDir.getPath() + File.separator + fileName;
File file = new File(realPath);
if (!file.exists() || !file.isFile()) {
response.sendError(404);
return;
}
// 未修改判断
String IfModifiedSince = request.getHeader("If-Modified-Since"); // Tue, 06 Jun 2017 06:04:45 GMT
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd, MMM yyyy hh:mm:ss z", Locale.ENGLISH);
if (IfModifiedSince != null) {
try {
Date date = sdf.parse(IfModifiedSince);
if (date.getTime() >= file.lastModify()) {
response.sendError(304);
return;
}
} catch(Exception e) {
System.out.println("解析If-Modified-Since失败");
}
}
long lastModified = file.lastModified; // sdf.format(new Date(f.getLastModify()));
String fileName = file.getName();
Path ffff = Paths.get(realPath);
// 处理文件读取的范围
int length = (int) Files.size(ffff);
int start = 0;
int end = length - 1;
String range = request.getHeader("Range");
range = range == null ? "" : range;
Matcher matcher = RANGE_PATTERN.matcher(range);
int status = 206;;
if (matcher.matches()) {
String startGroup = matcher.group("start");
start = startGroup.isEmpty() ? start : Integer.valueOf(startGroup);
start = start < 0 ? 0 : start;
String endGroup = matcher.group("end");
end = endGroup.isEmpty() ? end : Integer.valueOf(endGroup);
end = end > length - 1 ? length - 1 : end;
} else {
status = 200;
}
int contentLength = end - start + 1;
//
response.reset();
response.setBufferSize(BUFFER_LENGTH);
// 信息
response.setHeader("Content-Disposition", String.format("inline;filename=\"%s\"", fileName));
response.setContentType(Files.probeContentType(Paths.get(fileName)));
// response.setContentType("application/octet-stream");
// 缓存
response.setDateHeader("Last-Modified", lastModified);
response.setDateHeader("Expires", System.currentTimeMillis() + EXPIRE_TIME);
// 内容范围和长度
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Content-Range", String.format("bytes %s-%s/%s", start, end, length));
response.setHeader("Content-Length", String.format("%s", contentLength));
response.setStatus(status);
// 写出
int bytesRead;
int bytesLeft = contentLength;
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_LENGTH);
try (SeekableByteChannel input = Files.newByteChannel(ffff, StandardOpenOption.READ);
OutputStream output = response.getOutputStream()) {
input.position(start);
while ((bytesRead = input.read(buffer)) != -1 && bytesLeft > 0) {
buffer.clear();
output.write(buffer.array(), 0,
bytesLeft < bytesRead ? bytesLeft : bytesRead);
bytesLeft -= bytesRead;
}
}
}
<!DOCTYPE HTML>
<html>
<body>
<h4>播放视频</h4>
视频源URL<input id="url" style="min-width:400px;" value="http://localhost:8089/videc/test.mp4">
<button οnclick="loadvideo();">载入视频</button>
<br>
<span style="font-size:10px; color: #aaa;">视频源可以用nginx配置访问静态资源的方式搭建</span>
<br>
<video id="video_ele" src=""
controls="controls"
style="min-width: 400px; min-height: 300px;"
></video>
<script>
function vdonkeydown(event) {
var keynum;
var keychar;
keynum = window.event ? event.keyCode : event.which;
//keychar = String.fromCharCode(keynum);
//console.log(keynum+':'+keychar);
var e = document.getElementById("video_ele");
if (keynum == 32) { // space
if (e.paused)
e.play();
else
e.pause();
} else if (keynum == 37) { // left
var all = e.duration;
var v = e.currentTime;
v = v - 5;
if (v < 0)
v = 0;
e.currentTime = v;
} else if (keynum == 39) { // right
var all = e.duration;
var v = e.currentTime;
v = v + 5;
if (v > all)
v = all - 1;
e.currentTime = v;
} else if (keynum == 38) { // up
var v = e.volume;
v += 0.1;
if (v > 1)
v = 1;
e.volume = v;
} else if (keynum == 40) { // down
var v = e.volume;
v -= 0.1;
if (v < 0)
v = 0;
e.volume = v;
} else {
return true;
}
return false;
}
//单击双击判断
var dbclk = false;
function doclick(event) {
// pauseswitch();
//console.log(event.detail);
if (event.detail == 1) {
dbclk = false;
setTimeout(function() {
if (!dbclk) {
pauseswitch(); // 暂停切换
}
}, 300);
} else if (event.detail == 2) {
dbclk = true;
fullscreenswitch(); // 全屏切换
}
return false;
}
function pauseswitch() {
var e = document.getElementById("video_ele");
if (e.paused)
e.play();
else
e.pause();
}
function fullscreenswitch() {
var e = document.getElementById("video_ele");
// 这种全屏判断方法,也还行,如果f12时肯定不行
// console.log(e.scrollHeight + ' - ' + window.screen.height);
// console.log(document.body.scrollHeight + ' - ' + window.screen.height);
var bfullscreen = (document.body.scrollHeight == window.screen.height && document.body.scrollWidth == window.screen.width)
if (!bfullscreen) {
var e = document.getElementById("video_ele");
console.log("inter full screen");
if (e.requestFullscreen) { // w3c
e.requestFullscreen();
} else if (e.mozRequestFullScreen) { // FireFox
e.mozRequestFullScreen();
} else if (e.webkitRequestFullScreen) { // chrome
e.webkitRequestFullScreen();
} else if (e.msRequestFullscreen) { // IE11
e.msRequestFullscreen();
}
bfullscreen = true;
} else {
console.log("exist full screen");
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
bfullscreen = false;
}
}
function loadvideo() {
var e = document.getElementById("video_ele");
if (!e.paused)
e.pause();
e.src = document.getElementById("url").value;
return false;
}
(function(){
var e = document.getElementById("video_ele");
e.volume = 0.2;
e.onclick = doclick;
document.onkeydown = vdonkeydown;
})();
</script>
</body>
</html>