• java服务器端断点续传


    Servlet
    
    Java代码 复制代码 收藏代码
    import java.io.BufferedOutputStream;  
    import java.io.File;  
    import java.io.IOException;  
    import java.io.RandomAccessFile;  
    import java.io.UnsupportedEncodingException;  
    import java.net.URI;  
    import java.net.URISyntaxException;  
    import java.net.URLDecoder;  
      
    import javax.servlet.ServletException;  
    import javax.servlet.ServletOutputStream;  
    import javax.servlet.http.HttpServletRequest;  
    import javax.servlet.http.HttpServletResponse;  
      
    import com.bsteel.cloud.storage.servlet.base.BaseServlet;  
    import com.bsteel.cloud.storage.utils.FileUtil;  
      
      
    /** 
     * 文件下载(支持断点续传【迅雷快车旋风FirefoxChrome】) 
     * @author jdkleo 
     * 
     */  
    public class FileIoServlet extends BaseServlet {  
        private static final long serialVersionUID = 1L;  
          
        @Override  
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
                throws ServletException, IOException {  
            this.doPost(req, resp);  
        }  
          
        @Override  
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{  
            download(request,response);  
        }  
      
        /** 
         * 文件下载 
         * @param request 
         * @param response 
         * @throws UnsupportedEncodingException  
         */  
        private void download(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException {  
            File downloadFile = getFile(request);  
            long pos = FileUtil.headerSetting(downloadFile, request, response);  
    //      log.info("跳过"+pos);  
            ServletOutputStream os = null;   
            BufferedOutputStream out = null;  
            RandomAccessFile raf = null;  
            byte b[] = new byte[1024];//暂存容器  
            try {  
                os = response.getOutputStream();  
                out = new BufferedOutputStream(os);  
                raf = new RandomAccessFile(downloadFile, "r");  
                raf.seek(pos);  
                try {  
                        int n = 0;  
                        while ((n = raf.read(b, 0, 1024)) != -1) {  
                            out.write(b, 0, n);  
                        }  
                        out.flush();  
                } catch(IOException ie) {  
                }  
            } catch (Exception e) {  
                log.error(e.getMessage(), e);  
            } finally {  
                if (out != null) {  
                    try {  
                        out.close();  
                    } catch (IOException e) {  
                        log.error(e.getMessage(), e);  
                    }  
                }  
                if (raf != null) {  
                    try {  
                        raf.close();  
                    } catch (IOException e) {  
                        log.error(e.getMessage(), e);  
                    }  
                }  
            }  
        }  
          
        private File getFile(HttpServletRequest request) throws UnsupportedEncodingException {  
            String uriStr = request.getParameter("uri");  
            if (null != uriStr){  
                    uriStr = URLDecoder.decode(uriStr,"UTF-8");  
                    if (uriStr.startsWith("file://")){  
                        uriStr = uriStr.substring(7);  
                        return new File(uriStr);  
                    }else if (uriStr.startsWith("hbase://")){  
                        try {  
                            return new File(new URI(uriStr));  
                        } catch (URISyntaxException e) {  
                            log.error(e.getMessage(),e);  
                        }  
                    }  
            }  
            throw new RuntimeException("it's not a real uri");  
        }  
    }  
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.io.UnsupportedEncodingException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.net.URLDecoder;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.bsteel.cloud.storage.servlet.base.BaseServlet;
    import com.bsteel.cloud.storage.utils.FileUtil;
    
    
    /**
     * 文件下载(支持断点续传【迅雷快车旋风FirefoxChrome】)
     * @author jdkleo
     *
     */
    public class FileIoServlet extends BaseServlet {
    	private static final long serialVersionUID = 1L;
    	
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    			throws ServletException, IOException {
    		this.doPost(req, resp);
    	}
    	
    	@Override
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    		download(request,response);
    	}
    
    	/**
    	 * 文件下载
    	 * @param request
    	 * @param response
    	 * @throws UnsupportedEncodingException 
    	 */
    	private void download(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException {
    		File downloadFile = getFile(request);
    		long pos = FileUtil.headerSetting(downloadFile, request, response);
    //		log.info("跳过"+pos);
    		ServletOutputStream os = null; 
    		BufferedOutputStream out = null;
    		RandomAccessFile raf = null;
    		byte b[] = new byte[1024];//暂存容器
    		try {
    			os = response.getOutputStream();
    	    	out = new BufferedOutputStream(os);
    	    	raf = new RandomAccessFile(downloadFile, "r");
    	    	raf.seek(pos);
    	    	try {
    			        int n = 0;
    			        while ((n = raf.read(b, 0, 1024)) != -1) {
    			        	out.write(b, 0, n);
    			        }
    			        out.flush();
    	    	} catch(IOException ie) {
    	    	}
    		} catch (Exception e) {
    			log.error(e.getMessage(), e);
    		} finally {
    			if (out != null) {
    				try {
    					out.close();
    				} catch (IOException e) {
    					log.error(e.getMessage(), e);
    				}
    			}
    			if (raf != null) {
    				try {
    					raf.close();
    				} catch (IOException e) {
    					log.error(e.getMessage(), e);
    				}
    			}
    		}
    	}
    	
    	private File getFile(HttpServletRequest request) throws UnsupportedEncodingException {
    		String uriStr = request.getParameter("uri");
    		if (null != uriStr){
    				uriStr = URLDecoder.decode(uriStr,"UTF-8");
    				if (uriStr.startsWith("file://")){
    					uriStr = uriStr.substring(7);
    					return new File(uriStr);
    				}else if (uriStr.startsWith("hbase://")){
    					try {
    						return new File(new URI(uriStr));
    					} catch (URISyntaxException e) {
    						log.error(e.getMessage(),e);
    					}
    				}
    		}
    		throw new RuntimeException("it's not a real uri");
    	}
    }
     
    
    Range支持
    
    Java代码 复制代码 收藏代码
    import java.io.File;  
      
    import javax.servlet.http.HttpServletRequest;  
    import javax.servlet.http.HttpServletResponse;  
      
    /** 
     * 文件处理工具 
     * @author jdkleo 
     * 
     */  
    public class FileUtil {  
      
        /** 
         * 断点续传支持 
         * @param file 
         * @param request 
         * @param response 
         * @return 跳过多少字节 
         */  
        public static long headerSetting(File file,HttpServletRequest request, HttpServletResponse response) {  
            long len = file.length();//文件长度  
            if ( null == request.getHeader("Range") ){  
                setResponse(new RangeSettings(len),file.getName(),response);  
                return 0;  
            }  
            String range = request.getHeader("Range").replaceAll("bytes=", "");  
            RangeSettings settings = getSettings(len,range);  
            setResponse(settings,file.getName(),response);  
            return settings.getStart();  
        }  
      
        private static void setResponse(RangeSettings settings,String fileName, HttpServletResponse response) {  
              
            response.addHeader("Content-Disposition", "attachment; filename="" + IoUtil.toUtf8String(fileName) + """);  
            response.setContentType( IoUtil.setContentType(fileName));// set the MIME type.  
              
            if (!settings.isRange())  
            {  
                response.addHeader("Content-Length", String.valueOf(settings.getTotalLength()));  
            }  
            else  
            {  
                long start = settings.getStart();  
                long end = settings.getEnd();  
                long contentLength = settings.getContentLength();  
                  
                response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);  
          
                response.addHeader("Content-Length", String.valueOf(contentLength));  
                  
                String contentRange = new StringBuffer("bytes ").append(start).append("-").append(end).append("/").append(settings.getTotalLength()).toString();  
                response.setHeader("Content-Range", contentRange);  
            }  
        }  
      
        private static RangeSettings getSettings(long len, String range) {  
            long contentLength = 0;  
            long start = 0;  
            long end = 0;  
            if (range.startsWith("-"))// -500,最后500个  
            {  
                 contentLength = Long.parseLong(range.substring(1));//要下载的量  
                 end = len-1;  
                 start = len - contentLength;  
            }  
            else if (range.endsWith("-"))//从哪个开始  
            {  
                start = Long.parseLong(range.replace("-", ""));  
                end = len -1;  
                contentLength = len - start;  
            }  
            else//从a到b  
            {  
                String[] se = range.split("-");  
                start = Long.parseLong(se[0]);  
                end = Long.parseLong(se[1]);  
                contentLength = end-start+1;  
            }  
            return new RangeSettings(start,end,contentLength,len);  
        }  
          
          
      
    }  
    import java.io.File;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 文件处理工具
     * @author jdkleo
     *
     */
    public class FileUtil {
    
    	/**
    	 * 断点续传支持
    	 * @param file
    	 * @param request
    	 * @param response
    	 * @return 跳过多少字节
    	 */
    	public static long headerSetting(File file,HttpServletRequest request, HttpServletResponse response) {
    		long len = file.length();//文件长度
    		if ( null == request.getHeader("Range") ){
    			setResponse(new RangeSettings(len),file.getName(),response);
    			return 0;
    		}
    		String range = request.getHeader("Range").replaceAll("bytes=", "");
    		RangeSettings settings = getSettings(len,range);
    		setResponse(settings,file.getName(),response);
    		return settings.getStart();
    	}
    
    	private static void setResponse(RangeSettings settings,String fileName, HttpServletResponse response) {
    		
    		response.addHeader("Content-Disposition", "attachment; filename="" + IoUtil.toUtf8String(fileName) + """);
    		response.setContentType( IoUtil.setContentType(fileName));// set the MIME type.
    		
    		if (!settings.isRange())
    		{
    			response.addHeader("Content-Length", String.valueOf(settings.getTotalLength()));
    		}
    		else
    		{
    			long start = settings.getStart();
    			long end = settings.getEnd();
    			long contentLength = settings.getContentLength();
    			
    			response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
    	
    	        response.addHeader("Content-Length", String.valueOf(contentLength));
    	        
    	        String contentRange = new StringBuffer("bytes ").append(start).append("-").append(end).append("/").append(settings.getTotalLength()).toString();
    	        response.setHeader("Content-Range", contentRange);
    		}
    	}
    
    	private static RangeSettings getSettings(long len, String range) {
    		long contentLength = 0;
    		long start = 0;
    		long end = 0;
    		if (range.startsWith("-"))// -500,最后500个
    		{
    			 contentLength = Long.parseLong(range.substring(1));//要下载的量
    			 end = len-1;
    			 start = len - contentLength;
    		}
    		else if (range.endsWith("-"))//从哪个开始
    		{
    			start = Long.parseLong(range.replace("-", ""));
    			end = len -1;
    			contentLength = len - start;
    		}
    		else//从a到b
    		{
    			String[] se = range.split("-");
    			start = Long.parseLong(se[0]);
    			end = Long.parseLong(se[1]);
    			contentLength = end-start+1;
    		}
    		return new RangeSettings(start,end,contentLength,len);
    	}
    	
    	
    
    }
     
    
    Range封装
    
    Java代码 复制代码 收藏代码
    public class RangeSettings{  
      
            private long start;  
            private long end;  
            private long contentLength;  
            private long totalLength;  
            private boolean range;  
              
              
            public RangeSettings(){  
                super();  
            }  
      
            public RangeSettings(long start, long end, long contentLength,long totalLength) {  
                this.start = start;  
                this.end = end;  
                this.contentLength = contentLength;  
                this.totalLength = totalLength;  
                this.range = true;  
            }  
      
            public RangeSettings(long totalLength) {  
                this.totalLength = totalLength;  
            }  
      
            public long getStart() {  
                return start;  
            }  
      
            public void setStart(long start) {  
                this.start = start;  
            }  
      
            public long getEnd() {  
                return end;  
            }  
      
            public void setEnd(long end) {  
                this.end = end;  
            }  
      
            public long getContentLength() {  
                return contentLength;  
            }  
      
            public void setContentLength(long contentLength) {  
                this.contentLength = contentLength;  
            }  
      
            public long getTotalLength() {  
                return totalLength;  
            }  
      
            public void setTotalLength(long totalLength) {  
                this.totalLength = totalLength;  
            }  
              
            public boolean isRange() {  
                return range;  
            }  
      
              
        }   
    public class RangeSettings{
    
    		private long start;
    		private long end;
    		private long contentLength;
    		private long totalLength;
    		private boolean range;
    		
    		
    		public RangeSettings(){
    			super();
    		}
    
    		public RangeSettings(long start, long end, long contentLength,long totalLength) {
    			this.start = start;
    			this.end = end;
    			this.contentLength = contentLength;
    			this.totalLength = totalLength;
    			this.range = true;
    		}
    
    		public RangeSettings(long totalLength) {
    			this.totalLength = totalLength;
    		}
    
    		public long getStart() {
    			return start;
    		}
    
    		public void setStart(long start) {
    			this.start = start;
    		}
    
    		public long getEnd() {
    			return end;
    		}
    
    		public void setEnd(long end) {
    			this.end = end;
    		}
    
    		public long getContentLength() {
    			return contentLength;
    		}
    
    		public void setContentLength(long contentLength) {
    			this.contentLength = contentLength;
    		}
    
    		public long getTotalLength() {
    			return totalLength;
    		}
    
    		public void setTotalLength(long totalLength) {
    			this.totalLength = totalLength;
    		}
    		
    		public boolean isRange() {
    			return range;
    		}
    
    		
    	} 
     
    
    IO流相关处理工具类
    
     
    
    Java代码 复制代码 收藏代码
    import java.io.InputStream;  
      
    public class IoUtil {  
      
        public static String setContentType(String returnFileName){  
            String contentType = "application/octet-stream";  
            if (returnFileName.lastIndexOf(".") < 0)  
                return contentType;  
            returnFileName = returnFileName.toLowerCase();  
            returnFileName = returnFileName.substring(returnFileName.lastIndexOf(".")+1);  
              
            if (returnFileName.equals("html") || returnFileName.equals("htm") || returnFileName.equals("shtml")){  
                contentType = "text/html";  
            } else if (returnFileName.equals("css")){  
                contentType = "text/css";  
            } else if (returnFileName.equals("xml")){  
                contentType = "text/xml";  
            } else if (returnFileName.equals("gif")){  
                contentType = "image/gif";  
            } else if (returnFileName.equals("jpeg") || returnFileName.equals("jpg")){  
                contentType = "image/jpeg";  
            } else if (returnFileName.equals("js")){  
                contentType = "application/x-javascript";  
            } else if (returnFileName.equals("atom")){  
                contentType = "application/atom+xml";  
            } else if (returnFileName.equals("rss")){  
                contentType = "application/rss+xml";  
            } else if (returnFileName.equals("mml")){  
                contentType = "text/mathml";   
            } else if (returnFileName.equals("txt")){  
                contentType = "text/plain";  
            } else if (returnFileName.equals("jad")){  
                contentType = "text/vnd.sun.j2me.app-descriptor";  
            } else if (returnFileName.equals("wml")){  
                contentType = "text/vnd.wap.wml";  
            } else if (returnFileName.equals("htc")){  
                contentType = "text/x-component";  
            } else if (returnFileName.equals("png")){  
                contentType = "image/png";  
            } else if (returnFileName.equals("tif") || returnFileName.equals("tiff")){  
                contentType = "image/tiff";  
            } else if (returnFileName.equals("wbmp")){  
                contentType = "image/vnd.wap.wbmp";  
            } else if (returnFileName.equals("ico")){  
                contentType = "image/x-icon";  
            } else if (returnFileName.equals("jng")){  
                contentType = "image/x-jng";  
            } else if (returnFileName.equals("bmp")){  
                contentType = "image/x-ms-bmp";  
            } else if (returnFileName.equals("svg")){  
                contentType = "image/svg+xml";  
            } else if (returnFileName.equals("jar") || returnFileName.equals("var") || returnFileName.equals("ear")){  
                contentType = "application/java-archive";  
            } else if (returnFileName.equals("doc")){  
                contentType = "application/msword";  
            } else if (returnFileName.equals("pdf")){  
                contentType = "application/pdf";  
            } else if (returnFileName.equals("rtf")){  
                contentType = "application/rtf";  
            } else if (returnFileName.equals("xls")){  
                contentType = "application/vnd.ms-excel";   
            } else if (returnFileName.equals("ppt")){  
                contentType = "application/vnd.ms-powerpoint";  
            } else if (returnFileName.equals("7z")){  
                contentType = "application/x-7z-compressed";  
            } else if (returnFileName.equals("rar")){  
                contentType = "application/x-rar-compressed";  
            } else if (returnFileName.equals("swf")){  
                contentType = "application/x-shockwave-flash";  
            } else if (returnFileName.equals("rpm")){  
                contentType = "application/x-redhat-package-manager";  
            } else if (returnFileName.equals("der") || returnFileName.equals("pem") || returnFileName.equals("crt")){  
                contentType = "application/x-x509-ca-cert";  
            } else if (returnFileName.equals("xhtml")){  
                contentType = "application/xhtml+xml";  
            } else if (returnFileName.equals("zip")){  
                contentType = "application/zip";  
            } else if (returnFileName.equals("mid") || returnFileName.equals("midi") || returnFileName.equals("kar")){  
                contentType = "audio/midi";  
            } else if (returnFileName.equals("mp3")){  
                contentType = "audio/mpeg";  
            } else if (returnFileName.equals("ogg")){  
                contentType = "audio/ogg";  
            } else if (returnFileName.equals("m4a")){  
                contentType = "audio/x-m4a";  
            } else if (returnFileName.equals("ra")){  
                contentType = "audio/x-realaudio";  
            } else if (returnFileName.equals("3gpp") || returnFileName.equals("3gp")){  
                contentType = "video/3gpp";  
            } else if (returnFileName.equals("mp4") ){  
                contentType = "video/mp4";  
            } else if (returnFileName.equals("mpeg") || returnFileName.equals("mpg") ){  
                contentType = "video/mpeg";  
            } else if (returnFileName.equals("mov")){  
                contentType = "video/quicktime";  
            } else if (returnFileName.equals("flv")){  
                contentType = "video/x-flv";  
            } else if (returnFileName.equals("m4v")){  
                contentType = "video/x-m4v";  
            } else if (returnFileName.equals("mng")){  
                contentType = "video/x-mng";  
            } else if (returnFileName.equals("asx") || returnFileName.equals("asf")){  
                contentType = "video/x-ms-asf";  
            } else if (returnFileName.equals("wmv")){  
                contentType = "video/x-ms-wmv";  
            } else if (returnFileName.equals("avi")){  
                contentType = "video/x-msvideo";  
            }  
              
            return contentType;  
        }  
          
        // UTF8转码  
        public static String toUtf8String(String s) {  
            StringBuffer sb = new StringBuffer();  
            int len = s.toCharArray().length;  
            for (int i = 0; i < len; i++) {  
                char c = s.charAt(i);  
                if (c >= 0 && c <= 255) {  
                    sb.append(c);  
                } else {  
                    byte[] b;  
                    try {  
                        b = Character.toString(c).getBytes("utf-8");  
                    } catch (Exception ex) {  
                        System.out.println(ex);  
                        b = new byte[0];  
                    }  
                    for (int j = 0; j < b.length; j++) {  
                        int k = b[j];  
                        if (k < 0)  
                            k += 256;  
                        sb.append("%" + Integer.toHexString(k).toUpperCase());  
                    }  
                }  
            }  
            String s_utf8 = sb.toString();  
            sb.delete(0, sb.length());  
            sb.setLength(0);  
            sb = null;  
            return s_utf8;  
        }  
          
        public static InputStream skipFully(InputStream in,long howMany)throws Exception{  
            long remainning = howMany;  
            long len = 0;  
            while(remainning>0){  
                len = in.skip(len);  
                remainning -= len;  
            }  
            return in;  
        }  
          
    }  
    import java.io.InputStream;
    
    public class IoUtil {
    
    	public static String setContentType(String returnFileName){
    		String contentType = "application/octet-stream";
    		if (returnFileName.lastIndexOf(".") < 0)
    			return contentType;
    		returnFileName = returnFileName.toLowerCase();
    		returnFileName = returnFileName.substring(returnFileName.lastIndexOf(".")+1);
    		
    		if (returnFileName.equals("html") || returnFileName.equals("htm") || returnFileName.equals("shtml")){
    			contentType = "text/html";
    		} else if (returnFileName.equals("css")){
    			contentType = "text/css";
    		} else if (returnFileName.equals("xml")){
    			contentType = "text/xml";
    		} else if (returnFileName.equals("gif")){
    			contentType = "image/gif";
    		} else if (returnFileName.equals("jpeg") || returnFileName.equals("jpg")){
    			contentType = "image/jpeg";
    		} else if (returnFileName.equals("js")){
    			contentType = "application/x-javascript";
    		} else if (returnFileName.equals("atom")){
    			contentType = "application/atom+xml";
    		} else if (returnFileName.equals("rss")){
    			contentType = "application/rss+xml";
    		} else if (returnFileName.equals("mml")){
    			contentType = "text/mathml"; 
    		} else if (returnFileName.equals("txt")){
    			contentType = "text/plain";
    		} else if (returnFileName.equals("jad")){
    			contentType = "text/vnd.sun.j2me.app-descriptor";
    		} else if (returnFileName.equals("wml")){
    			contentType = "text/vnd.wap.wml";
    		} else if (returnFileName.equals("htc")){
    			contentType = "text/x-component";
    		} else if (returnFileName.equals("png")){
    			contentType = "image/png";
    		} else if (returnFileName.equals("tif") || returnFileName.equals("tiff")){
    			contentType = "image/tiff";
    		} else if (returnFileName.equals("wbmp")){
    			contentType = "image/vnd.wap.wbmp";
    		} else if (returnFileName.equals("ico")){
    			contentType = "image/x-icon";
    		} else if (returnFileName.equals("jng")){
    			contentType = "image/x-jng";
    		} else if (returnFileName.equals("bmp")){
    			contentType = "image/x-ms-bmp";
    		} else if (returnFileName.equals("svg")){
    			contentType = "image/svg+xml";
    		} else if (returnFileName.equals("jar") || returnFileName.equals("var") || returnFileName.equals("ear")){
    			contentType = "application/java-archive";
    		} else if (returnFileName.equals("doc")){
    			contentType = "application/msword";
    		} else if (returnFileName.equals("pdf")){
    			contentType = "application/pdf";
    		} else if (returnFileName.equals("rtf")){
    			contentType = "application/rtf";
    		} else if (returnFileName.equals("xls")){
    			contentType = "application/vnd.ms-excel"; 
    		} else if (returnFileName.equals("ppt")){
    			contentType = "application/vnd.ms-powerpoint";
    		} else if (returnFileName.equals("7z")){
    			contentType = "application/x-7z-compressed";
    		} else if (returnFileName.equals("rar")){
    			contentType = "application/x-rar-compressed";
    		} else if (returnFileName.equals("swf")){
    			contentType = "application/x-shockwave-flash";
    		} else if (returnFileName.equals("rpm")){
    			contentType = "application/x-redhat-package-manager";
    		} else if (returnFileName.equals("der") || returnFileName.equals("pem") || returnFileName.equals("crt")){
    			contentType = "application/x-x509-ca-cert";
    		} else if (returnFileName.equals("xhtml")){
    			contentType = "application/xhtml+xml";
    		} else if (returnFileName.equals("zip")){
    			contentType = "application/zip";
    		} else if (returnFileName.equals("mid") || returnFileName.equals("midi") || returnFileName.equals("kar")){
    			contentType = "audio/midi";
    		} else if (returnFileName.equals("mp3")){
    			contentType = "audio/mpeg";
    		} else if (returnFileName.equals("ogg")){
    			contentType = "audio/ogg";
    		} else if (returnFileName.equals("m4a")){
    			contentType = "audio/x-m4a";
    		} else if (returnFileName.equals("ra")){
    			contentType = "audio/x-realaudio";
    		} else if (returnFileName.equals("3gpp") || returnFileName.equals("3gp")){
    			contentType = "video/3gpp";
    		} else if (returnFileName.equals("mp4") ){
    			contentType = "video/mp4";
    		} else if (returnFileName.equals("mpeg") || returnFileName.equals("mpg") ){
    			contentType = "video/mpeg";
    		} else if (returnFileName.equals("mov")){
    			contentType = "video/quicktime";
    		} else if (returnFileName.equals("flv")){
    			contentType = "video/x-flv";
    		} else if (returnFileName.equals("m4v")){
    			contentType = "video/x-m4v";
    		} else if (returnFileName.equals("mng")){
    			contentType = "video/x-mng";
    		} else if (returnFileName.equals("asx") || returnFileName.equals("asf")){
    			contentType = "video/x-ms-asf";
    		} else if (returnFileName.equals("wmv")){
    			contentType = "video/x-ms-wmv";
    		} else if (returnFileName.equals("avi")){
    			contentType = "video/x-msvideo";
    		}
    		
    		return contentType;
    	}
    	
    	// UTF8转码
    	public static String toUtf8String(String s) {
    		StringBuffer sb = new StringBuffer();
    		int len = s.toCharArray().length;
    		for (int i = 0; i < len; i++) {
    			char c = s.charAt(i);
    			if (c >= 0 && c <= 255) {
    				sb.append(c);
    			} else {
    				byte[] b;
    				try {
    					b = Character.toString(c).getBytes("utf-8");
    				} catch (Exception ex) {
    					System.out.println(ex);
    					b = new byte[0];
    				}
    				for (int j = 0; j < b.length; j++) {
    					int k = b[j];
    					if (k < 0)
    						k += 256;
    					sb.append("%" + Integer.toHexString(k).toUpperCase());
    				}
    			}
    		}
    		String s_utf8 = sb.toString();
    		sb.delete(0, sb.length());
    		sb.setLength(0);
    		sb = null;
    		return s_utf8;
    	}
    	
    	public static InputStream skipFully(InputStream in,long howMany)throws Exception{
            long remainning = howMany;
            long len = 0;
            while(remainning>0){
                len = in.skip(len);
                remainning -= len;
            }
            return in;
        }
    	
    }
      
    

      

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     ArcSyncHttpDownloadServlet 源代码:
    
    
    
    
    [java] view plaincopyprint?
    01.package com.defonds.cds.common;  
    02.  
    03.import java.io.BufferedOutputStream;  
    04.import java.io.File;  
    05.import java.io.IOException;  
    06.import java.io.OutputStream;  
    07.import java.io.RandomAccessFile;  
    08.  
    09.import javax.servlet.ServletException;  
    10.import javax.servlet.http.HttpServlet;  
    11.import javax.servlet.http.HttpServletRequest;  
    12.import javax.servlet.http.HttpServletResponse;  
    13.  
    14.import org.apache.commons.logging.Log;  
    15.import org.apache.commons.logging.LogFactory;  
    16.  
    17.import com.defonds.cds.common.util.CommonUtil;  
    18.  
    19.//HTTP 断点续传 demo(客户端测试工具:快车、迅雷)  
    20.public class ArcSyncHttpDownloadServlet extends HttpServlet {  
    21.    private static final long serialVersionUID = 1L;  
    22.    final static Log log = LogFactory.getLog(ArcSyncHttpDownloadServlet.class);  
    23.      
    24.    @Override  
    25.    protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
    26.            throws ServletException, IOException {  
    27.        this.doPost(req, resp);  
    28.    }  
    29.      
    30.    @Override  
    31.    protected void doPost(HttpServletRequest request, HttpServletResponse response) {  
    32.        File downloadFile = new File("D:/defonds/book/pattern/SteveJobsZH.pdf");//要下载的文件  
    33.        long fileLength = downloadFile.length();//记录文件大小  
    34.        long pastLength = 0;//记录已下载文件大小  
    35.        int rangeSwitch = 0;//0:从头开始的全文下载;1:从某字节开始的下载(bytes=27000-);2:从某字节开始到某字节结束的下载(bytes=27000-39000)  
    36.        long toLength = 0;//记录客户端需要下载的字节段的最后一个字节偏移量(比如bytes=27000-39000,则这个值是为39000)  
    37.        long contentLength = 0;//客户端请求的字节总量  
    38.        String rangeBytes = "";//记录客户端传来的形如“bytes=27000-”或者“bytes=27000-39000”的内容   
    39.        RandomAccessFile raf = null;//负责读取数据  
    40.        OutputStream os = null;//写出数据  
    41.        OutputStream out = null;//缓冲  
    42.        byte b[] = new byte[1024];//暂存容器  
    43.          
    44.        if (request.getHeader("Range") != null) {// 客户端请求的下载的文件块的开始字节  
    45.            response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);  
    46.            log.info("request.getHeader("Range")=" + request.getHeader("Range"));  
    47.            rangeBytes = request.getHeader("Range").replaceAll("bytes=", "");  
    48.            if (rangeBytes.indexOf('-') == rangeBytes.length() - 1) {//bytes=969998336-  
    49.                rangeSwitch = 1;  
    50.                rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf('-'));  
    51.                pastLength = Long.parseLong(rangeBytes.trim());  
    52.                contentLength = fileLength - pastLength + 1;//客户端请求的是 969998336 之后的字节  
    53.            } else {//bytes=1275856879-1275877358  
    54.                rangeSwitch = 2;  
    55.                String temp0 = rangeBytes.substring(0,rangeBytes.indexOf('-'));  
    56.                String temp2 = rangeBytes.substring(rangeBytes.indexOf('-') + 1, rangeBytes.length());  
    57.                pastLength = Long.parseLong(temp0.trim());//bytes=1275856879-1275877358,从第 1275856879 个字节开始下载  
    58.                toLength = Long.parseLong(temp2);//bytes=1275856879-1275877358,到第 1275877358 个字节结束  
    59.                contentLength = toLength - pastLength + 1;//客户端请求的是 1275856879-1275877358  之间的字节  
    60.            }  
    61.        } else {//从开始进行下载  
    62.            contentLength = fileLength;//客户端要求全文下载  
    63.        }  
    64.          
    65.        /** 
    66.         * 如果设设置了Content-Length,则客户端会自动进行多线程下载。如果不希望支持多线程,则不要设置这个参数。 
    67.         * 响应的格式是: 
    68.         * Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节] 
    69.         * ServletActionContext.getResponse().setHeader("Content-Length", 
    70.         * new Long(file.length() - p).toString()); 
    71.         */  
    72.        response.reset();//告诉客户端允许断点续传多线程连接下载,响应的格式是:Accept-Ranges: bytes  
    73.        response.setHeader("Accept-Ranges", "bytes");//如果是第一次下,还没有断点续传,状态是默认的 200,无需显式设置;响应的格式是:HTTP/1.1 200 OK  
    74.        if (pastLength != 0) {  
    75.            //不是从最开始下载,  
    76.            //响应的格式是:  
    77.            //Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]  
    78.            log.info("----------------------------不是从开始进行下载!服务器即将开始断点续传...");  
    79.            switch (rangeSwitch) {  
    80.                case 1 : {//针对 bytes=27000- 的请求  
    81.                    String contentRange = new StringBuffer("bytes ").append(new Long(pastLength).toString()).append("-").append(new Long(fileLength - 1).toString()).append("/").append(new Long(fileLength).toString()).toString();  
    82.                    response.setHeader("Content-Range", contentRange);  
    83.                    break;  
    84.                }  
    85.                case 2 : {//针对 bytes=27000-39000 的请求  
    86.                    String contentRange = rangeBytes + "/" + new Long(fileLength).toString();  
    87.                    response.setHeader("Content-Range", contentRange);  
    88.                    break;  
    89.                }  
    90.                default : {  
    91.                    break;  
    92.                }  
    93.            }  
    94.        } else {  
    95.            //是从开始下载  
    96.            log.info("----------------------------是从开始进行下载!");  
    97.        }  
    98.          
    99.        try {  
    100.            response.addHeader("Content-Disposition", "attachment; filename="" + downloadFile.getName() + """);  
    101.            response.setContentType( CommonUtil.setContentType(downloadFile.getName()));// set the MIME type.  
    102.            response.addHeader("Content-Length", String.valueOf(contentLength));  
    103.            os = response.getOutputStream();  
    104.            out = new BufferedOutputStream(os);  
    105.            raf = new RandomAccessFile(downloadFile, "r");  
    106.            try {  
    107.                switch (rangeSwitch) {  
    108.                    case 0 : {//普通下载,或者从头开始的下载  
    109.                        //同1  
    110.                    }  
    111.                    case 1 : {//针对 bytes=27000- 的请求  
    112.                        raf.seek(pastLength);//形如 bytes=969998336- 的客户端请求,跳过 969998336  个字节  
    113.                        int n = 0;  
    114.                        while ((n = raf.read(b, 0, 1024)) != -1) {  
    115.                            out.write(b, 0, n);  
    116.                        }  
    117.                        break;  
    118.                    }  
    119.                    case 2 : {//针对 bytes=27000-39000 的请求  
    120.                        raf.seek(pastLength - 1);//形如 bytes=1275856879-1275877358 的客户端请求,找到第 1275856879 个字节  
    121.                        int n = 0;  
    122.                        long readLength = 0;//记录已读字节数  
    123.                        while (readLength <= contentLength - 1024) {//大部分字节在这里读取  
    124.                            n = raf.read(b, 0, 1024);  
    125.                            readLength += 1024;  
    126.                            out.write(b, 0, n);  
    127.                        }  
    128.                        if (readLength <= contentLength) {//余下的不足 1024 个字节在这里读取  
    129.                            n = raf.read(b, 0, (int)(contentLength - readLength));  
    130.                            out.write(b, 0, n);  
    131.                        }  
    132.//                        
    133.//                      raf.seek(pastLength);//形如 bytes=1275856879-1275877358 的客户端请求,找到第 1275856879 个字节  
    134.//                      while (raf.getFilePointer() < toLength) {  
    135.//                          out.write(raf.read());  
    136.//                      }  
    137.                        break;  
    138.                    }  
    139.                    default : {  
    140.                        break;  
    141.                    }  
    142.                }  
    143.                out.flush();  
    144.            } catch(IOException ie) {  
    145.                /** 
    146.                 * 在写数据的时候, 
    147.                 * 对于 ClientAbortException 之类的异常, 
    148.                 * 是因为客户端取消了下载,而服务器端继续向浏览器写入数据时, 
    149.                 * 抛出这个异常,这个是正常的。 
    150.                 * 尤其是对于迅雷这种吸血的客户端软件, 
    151.                 * 明明已经有一个线程在读取 bytes=1275856879-1275877358, 
    152.                 * 如果短时间内没有读取完毕,迅雷会再启第二个、第三个。。。线程来读取相同的字节段, 
    153.                 * 直到有一个线程读取完毕,迅雷会 KILL 掉其他正在下载同一字节段的线程, 
    154.                 * 强行中止字节读出,造成服务器抛 ClientAbortException。 
    155.                 * 所以,我们忽略这种异常 
    156.                 */  
    157.                //ignore  
    158.            }  
    159.        } catch (Exception e) {  
    160.            log.error(e.getMessage(), e);  
    161.        } finally {  
    162.            if (out != null) {  
    163.                try {  
    164.                    out.close();  
    165.                } catch (IOException e) {  
    166.                    log.error(e.getMessage(), e);  
    167.                }  
    168.            }  
    169.            if (raf != null) {  
    170.                try {  
    171.                    raf.close();  
    172.                } catch (IOException e) {  
    173.                    log.error(e.getMessage(), e);  
    174.                }  
    175.            }  
    176.        }  
    177.    }  
    178.}  
    
    
    
    
    
            ArcSyncHttpDownloadServlet 的 web.xml 配置清单:
    
    
    
    
    [html] view plaincopyprint?
    01.    <!-- HTTP 断点续传 demo:127.0.0.1/cds/http -->  
    02.<servlet>  
    03.    <servlet-name>httpServlet</servlet-name>  
    04.    <servlet-class>com.defonds.cds.common.ArcSyncHttpDownloadServlet</servlet-class>  
    05.</servlet>      
    06.<servlet-mapping>  
    07.    <servlet-name>httpServlet</servlet-name>  
    08.    <url-pattern>/http</url-pattern>  
    09.</servlet-mapping>      
    
    
    
    
    
            ArcSyncHttpDownloadServlet 调用到的工具类 com.defonds.cds.common.util.CommonUtil 源代码:
    
    
    
    
    [java] view plaincopyprint?
    01.package com.defonds.cds.common.util;  
    02.  
    03.public class CommonUtil {  
    04.  
    05.    public static String setContentType(String returnFileName){  
    06.        String contentType = "application/octet-stream";  
    07.        if (returnFileName.lastIndexOf(".") < 0)  
    08.            return contentType;  
    09.        returnFileName = returnFileName.toLowerCase();  
    10.        returnFileName = returnFileName.substring(returnFileName.lastIndexOf(".")+1);  
    11.          
    12.        if (returnFileName.equals("html") || returnFileName.equals("htm") || returnFileName.equals("shtml")){  
    13.            contentType = "text/html";  
    14.        } else if (returnFileName.equals("css")){  
    15.            contentType = "text/css";  
    16.        } else if (returnFileName.equals("xml")){  
    17.            contentType = "text/xml";  
    18.        } else if (returnFileName.equals("gif")){  
    19.            contentType = "image/gif";  
    20.        } else if (returnFileName.equals("jpeg") || returnFileName.equals("jpg")){  
    21.            contentType = "image/jpeg";  
    22.        } else if (returnFileName.equals("js")){  
    23.            contentType = "application/x-javascript";  
    24.        } else if (returnFileName.equals("atom")){  
    25.            contentType = "application/atom+xml";  
    26.        } else if (returnFileName.equals("rss")){  
    27.            contentType = "application/rss+xml";  
    28.        } else if (returnFileName.equals("mml")){  
    29.            contentType = "text/mathml";   
    30.        } else if (returnFileName.equals("txt")){  
    31.            contentType = "text/plain";  
    32.        } else if (returnFileName.equals("jad")){  
    33.            contentType = "text/vnd.sun.j2me.app-descriptor";  
    34.        } else if (returnFileName.equals("wml")){  
    35.            contentType = "text/vnd.wap.wml";  
    36.        } else if (returnFileName.equals("htc")){  
    37.            contentType = "text/x-component";  
    38.        } else if (returnFileName.equals("png")){  
    39.            contentType = "image/png";  
    40.        } else if (returnFileName.equals("tif") || returnFileName.equals("tiff")){  
    41.            contentType = "image/tiff";  
    42.        } else if (returnFileName.equals("wbmp")){  
    43.            contentType = "image/vnd.wap.wbmp";  
    44.        } else if (returnFileName.equals("ico")){  
    45.            contentType = "image/x-icon";  
    46.        } else if (returnFileName.equals("jng")){  
    47.            contentType = "image/x-jng";  
    48.        } else if (returnFileName.equals("bmp")){  
    49.            contentType = "image/x-ms-bmp";  
    50.        } else if (returnFileName.equals("svg")){  
    51.            contentType = "image/svg+xml";  
    52.        } else if (returnFileName.equals("jar") || returnFileName.equals("var") || returnFileName.equals("ear")){  
    53.            contentType = "application/java-archive";  
    54.        } else if (returnFileName.equals("doc")){  
    55.            contentType = "application/msword";  
    56.        } else if (returnFileName.equals("pdf")){  
    57.            contentType = "application/pdf";  
    58.        } else if (returnFileName.equals("rtf")){  
    59.            contentType = "application/rtf";  
    60.        } else if (returnFileName.equals("xls")){  
    61.            contentType = "application/vnd.ms-excel";   
    62.        } else if (returnFileName.equals("ppt")){  
    63.            contentType = "application/vnd.ms-powerpoint";  
    64.        } else if (returnFileName.equals("7z")){  
    65.            contentType = "application/x-7z-compressed";  
    66.        } else if (returnFileName.equals("rar")){  
    67.            contentType = "application/x-rar-compressed";  
    68.        } else if (returnFileName.equals("swf")){  
    69.            contentType = "application/x-shockwave-flash";  
    70.        } else if (returnFileName.equals("rpm")){  
    71.            contentType = "application/x-redhat-package-manager";  
    72.        } else if (returnFileName.equals("der") || returnFileName.equals("pem") || returnFileName.equals("crt")){  
    73.            contentType = "application/x-x509-ca-cert";  
    74.        } else if (returnFileName.equals("xhtml")){  
    75.            contentType = "application/xhtml+xml";  
    76.        } else if (returnFileName.equals("zip")){  
    77.            contentType = "application/zip";  
    78.        } else if (returnFileName.equals("mid") || returnFileName.equals("midi") || returnFileName.equals("kar")){  
    79.            contentType = "audio/midi";  
    80.        } else if (returnFileName.equals("mp3")){  
    81.            contentType = "audio/mpeg";  
    82.        } else if (returnFileName.equals("ogg")){  
    83.            contentType = "audio/ogg";  
    84.        } else if (returnFileName.equals("m4a")){  
    85.            contentType = "audio/x-m4a";  
    86.        } else if (returnFileName.equals("ra")){  
    87.            contentType = "audio/x-realaudio";  
    88.        } else if (returnFileName.equals("3gpp") || returnFileName.equals("3gp")){  
    89.            contentType = "video/3gpp";  
    90.        } else if (returnFileName.equals("mp4") ){  
    91.            contentType = "video/mp4";  
    92.        } else if (returnFileName.equals("mpeg") || returnFileName.equals("mpg") ){  
    93.            contentType = "video/mpeg";  
    94.        } else if (returnFileName.equals("mov")){  
    95.            contentType = "video/quicktime";  
    96.        } else if (returnFileName.equals("flv")){  
    97.            contentType = "video/x-flv";  
    98.        } else if (returnFileName.equals("m4v")){  
    99.            contentType = "video/x-m4v";  
    100.        } else if (returnFileName.equals("mng")){  
    101.            contentType = "video/x-mng";  
    102.        } else if (returnFileName.equals("asx") || returnFileName.equals("asf")){  
    103.            contentType = "video/x-ms-asf";  
    104.        } else if (returnFileName.equals("wmv")){  
    105.            contentType = "video/x-ms-wmv";  
    106.        } else if (returnFileName.equals("avi")){  
    107.            contentType = "video/x-msvideo";  
    108.        }  
    109.          
    110.        return contentType;  
    111.    }  
    112.      
    113.      
    114.}  
  • 相关阅读:
    DeprecationWarning:'open()' is deprecated in mongoose>=4.11.0,use 'openUri()' instead or set the 'useMongoClient' option if using 'connect()' or 'createConnection'
    javascript if else优化指南
    前端上传文件的几种方式
    前端图片优化
    微信小程序中利用时间选择器和js无计算实现定时器(将字符串或秒数转换成倒计时)
    javascript之闭包理解以及应用场景
    网页或微信小程序中使元素占满整个屏幕高度
    微信小程序定时器组件(输入时间字符串即可倒计时)
    自己用js实现全屏滚动
    js获取屏幕宽高
  • 原文地址:https://www.cnblogs.com/systemnet123/p/3190871.html
Copyright © 2020-2023  润新知