概述
最近做的项目涉及到视频播放,开始只是把视频的路径交给播放插件,但是
发现视频加载的速度有些慢,并且视频越大加载时间越长,于是使用了断点续传对视频播放
进行了优化。
断点续传原理
断点续传的理解可以分为两部分:一部分是断点,一部分是续传。断点的由来是在下载过程中,将一个下载文件分成了多个部分,
同时进行多个部分一起的下载,当某个时间点,任务被暂停了,此时下载暂停的位置就是断点了。续传就是当一个未完成的下载任务再次开始时,
会从上次的断点继续传送。使用多线程断点续传下载的时候,将下载或上传任务人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,
多个线程并发可以占用服务器端更多资源,从而加快下载速度。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| public void player(String path,HttpServletRequest request, HttpServletResponse response) { String newPath = path.substring(path.indexOf(Global.USERFILES_BASE_URL),path.length()); String absolutePath = "" ; try { absolutePath = request.getSession().getServletContext().getRealPath(URLDecoder.decode(newPath,"utf-8")); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } BufferedInputStream bis = null; try { File file = new File(absolutePath); if (file.exists()) { long p = 0L; long toLength = 0L; long contentLength = 0L; int rangeSwitch = 0; long fileLength; String rangBytes = ""; fileLength = file.length();
InputStream ins = new FileInputStream(file); bis = new java.io.BufferedInputStream(ins);
response.reset(); response.setHeader("Accept-Ranges", "bytes");
String range = request.getHeader("Range"); if (range != null && range.trim().length() > 0 && !"null".equals(range)) { response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT); rangBytes = range.replaceAll("bytes=", ""); if (rangBytes.endsWith("-")) { rangeSwitch = 1; p = Long.parseLong(rangBytes.substring(0, rangBytes.indexOf("-"))); contentLength = fileLength - p; } else { rangeSwitch = 2; String temp1 = rangBytes.substring(0, rangBytes.indexOf("-")); String temp2 = rangBytes.substring(rangBytes.indexOf("-") + 1, rangBytes.length()); p = Long.parseLong(temp1); toLength = Long.parseLong(temp2); contentLength = toLength - p + 1; } } else { contentLength = fileLength; }
response.setHeader("Content-Length", new Long(contentLength).toString());
if (rangeSwitch == 1) { String contentRange = new StringBuffer("bytes ").append(new Long(p).toString()).append("-") .append(new Long(fileLength - 1).toString()).append("/") .append(new Long(fileLength).toString()).toString(); response.setHeader("Content-Range", contentRange); bis.skip(p); } else if (rangeSwitch == 2) { String contentRange = range.replace("=", " ") + "/" + new Long(fileLength).toString(); response.setHeader("Content-Range", contentRange); bis.skip(p); } else { String contentRange = new StringBuffer("bytes ").append("0-").append(fileLength - 1).append("/") .append(fileLength).toString(); response.setHeader("Content-Range", contentRange); }
String fileName = file.getName(); response.setContentType("application/octet-stream"); response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
OutputStream out = response.getOutputStream(); int n = 0; long readLength = 0; int bsize = 1024; byte[] bytes = new byte[bsize]; if (rangeSwitch == 2) { while (readLength <= contentLength - bsize) { n = bis.read(bytes); readLength += n; out.write(bytes, 0, n); } if (readLength <= contentLength) { n = bis.read(bytes, 0, (int) (contentLength - readLength)); out.write(bytes, 0, n); } } else { while ((n = bis.read(bytes)) != -1) { out.write(bytes, 0, n); } } out.flush(); out.close(); bis.close(); } } catch (java.io.IOException ie) { } catch (Exception e) { e.printStackTrace(); } }
|