断点续传JAVA实现

java

浏览数:78

2019-1-8


支持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);
            }

        }
    }

}