zoukankan      html  css  js  c++  java
  • 断点续传JAVA实现


    支持H5 Video标签播放,迅雷下载

    
    /**
     * 断点续传工具
     * @author lxycx_xc
     * 时间:2017年11月30日
     */
    public class BreakpointResume {
    	
    	private static Logger log = Logger.getLogger(BreakpointResume.class);
    	
    	
    	/**下载操作,支持断点续传*/
    	public static void download(HttpServletRequest req,HttpServletResponse resp,String filepath) throws NumberFormatException, IOException{
    		//请求头参数
    		File file = new File(filepath);
    		Long fileSize = file.length();
    		Long lasttime = file.lastModified();
    		Long size = fileSize;
    		int i = 0;
    		
    		String range = req.getHeader("Range");
    		String ifm = req.getHeader("If-Modified-Since");
    		if(ifm!=null&&Long.parseLong(ifm)<lasttime){//检查文件修改时间判断是否启用缓存
    			resp.setStatus(304);
    		}else{
    			byte[] buff = new byte[524288];//1024*1024/2
    			RandomAccessFile raf  = new RandomAccessFile(file, "rw");
    			BufferedOutputStream bfo = new BufferedOutputStream(resp.getOutputStream());
    
    			try {
    				if(range!=null){//断点续传请求			
    					size = (long)(5242880);//限制每次视频输出的大小 
    					String[] ranges = range.replace("bytes=", "").split("-");
    					
    					if(ranges.length<2){//为Content-Range参数做铺垫
    						ranges = new String[]{ranges[0],"0"};
    						if(fileSize-Long.parseLong(ranges[0])>size){
    							ranges[1] = String.valueOf(Long.parseLong(ranges[0])+size);	
    						}else{
    							ranges[1] = String.valueOf(fileSize-1);						
    						}
    					}
    					
    					raf.seek(Long.parseLong(ranges[0]));//从指定位置开始读取
    					resp.setHeader("Last-Modified", String.valueOf(lasttime));//文件最后修改时间
    					resp.setHeader("Content-Range", "bytes "+StringUtils.join(ranges, "-")+"/"+fileSize);//请求的数据 开始-结束/文件总大小
    					resp.setStatus(206);
    				}
    				int len = 0;
    				while((len=raf.read(buff))>0&&i<size){
    
    					bfo.write(buff);
    					bfo.flush();
    					i+=len;
    					
    					log.debug("本次输出:"+buff.length);
    				}
    			} catch (Exception e) {
    				log.info("输出流非正常关闭:");
    			} finally{
    				raf.close();
    				bfo.close();
    				log.info("当前请求共输出:"+i);
    			}
    
    		}
    	}
    
    }
    
    
  • 相关阅读:
    置换加密算法
    堆和优先队列的应用
    定时发送邮件小程序
    Hibernate的缓存
    Spring中使用JDBC
    Spring AOP(创建切面)
    处理不可中断阻塞
    SQL语句实例说明
    spring_声明式事务
    Flex_includeIn属性的作用
  • 原文地址:https://www.cnblogs.com/qixidi/p/10219606.html
Copyright © 2011-2022 走看看