博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 支持断点续传功能实现
阅读量:7202 次
发布时间:2019-06-29

本文共 7312 字,大约阅读时间需要 24 分钟。

hot3.png

服务器端代码:

package *;import java.io.*;import java.net.URLDecoder;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import biz.etao.appmarket.core.utils.StringUtil;/** * 客户端下载文件的统一入口 已支持断点续传 *  * @author lianggj,charlie.deng */@WebServlet(value = "/download/*")public class FileDownloadServlet extends HttpServlet {   private Logger logger = LoggerFactory.getLogger(FileDownloadServlet.class);   /**    * Comment for serialVersionUID    */   private static final long serialVersionUID = 2822257745268393246L;   public void init() throws ServletException {      logger.info(FileDownloadServlet.class.getName() + " is inited.");   }   public void destroy() {      super.destroy();   }   /**    * 下载文件 已支持断点续传    */   public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {      String base = "/download/";      String url = request.getRequestURI();      String path = url.substring(url.indexOf(base) + base.length());      path = URLDecoder.decode(path, "UTF-8");      // 获取文件对象信息      File file = new File(StringUtil.getFileTempReplace() + path);      if (!file.exists()) {         response.setStatus(404);         return;      }      BufferedInputStream bis = null;      try {         String fileName = file.getName();         long fileLength = file.length();         long start = 0, end = fileLength - 1, contentLength = fileLength;         String range = request.getHeader("Range");         if (range != null) {            // client requests a file block download start byte            String[] fromTo = range.split("=")[1].split("-");            start = Long.parseLong(fromTo[0]);            if (fromTo.length == 2 && fromTo[1] != null && !fromTo[1].equals(""))               end = Long.parseLong(fromTo[1]);            if (end >= fileLength)               end = fileLength - 1;         }         contentLength = end - start + 1;         // support multi-threaded download         // respone format:         // Content-Length:[file size] - [client request start bytes from         // file block]         // tell the client to allow accept-ranges         response.reset();         response.setHeader("Accept-Ranges", "bytes");         response.setContentLengthLong(contentLength);         // String contentType =         // Files.probeContentType(Paths.get(file.getPath()));         String contentType = request.getSession().getServletContext().getMimeType(fileName);         if (contentType == null && file.getPath().endsWith(".apk"))            contentType = "application/vnd.android.package-archive";         response.setContentType(contentType);         if (start > 0) {            response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);            // 断点开始            // 响应的格式是:            // Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]            String contentRange = new StringBuffer("bytes ").append(start).append("-").append(end).append("/")                  .append(contentLength).toString();            response.setHeader("Content-Range", contentRange);         }         response.addHeader("Content-Disposition",               "attachment;filename=" + new String(fileName.getBytes("utf-8"), "ISO8859-1"));         // response.addHeader("Last-Modified:Mon", file.getvalue);         // get file content         byte[] buffer = new byte[4096];         int length = 0;         long count = 0;         OutputStream out = response.getOutputStream();         InputStream ins = new FileInputStream(file);         bis = new BufferedInputStream(ins);         if (start > 0) {            // pointer move to seek            bis.skip(start);         }         while ((length = bis.read(buffer)) != -1 && count < contentLength) {            out.write(buffer, 0, length);            count += length;         }         response.flushBuffer();      } catch (Exception ex) {         String msg = this.getClass().getName() + ".doGet() error: " + ex.toString();         logger.error(msg);         throw new ServletException(ex);      } finally {         if (bis != null)            bis.close();      }   }}

客服端代码:

public class TestDownload {     /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        HttpURLConnection httpURLConnection = null;        URL url = null;        BufferedInputStream bis = null;        byte[] buf = new byte[10240];        int size = 0;        String fileName = "aaa.zip";        String filePath = "C:\\Users\\Desktop";        String remoteUrl = "http://127.0.0.1:8080/down.zip";         // 检查本地文件        RandomAccessFile rndFile = null;        File file = new File(filePath + "\\" + fileName);        long remoteFileSize = getRemoteFileSzie(remoteUrl);        long nPos = 0;                if (file.exists()) {                                   long localFileSzie = file.length();            if (localFileSzie < remoteFileSize) {                                   System.out.println("文件续传...");                nPos = localFileSzie;            } else {                System.out.println("文件存在,重新下载...");                file.delete();                try {                    file.createNewFile();                } catch (Exception e) {                    // TODO: handle exception                    e.printStackTrace();                }               }                    } else {            // 建立文件            try {                file.createNewFile();            } catch (Exception e) {                // TODO: handle exception                e.printStackTrace();            }                   }                // 下载文件        try {            url = new URL(remoteUrl);                   httpURLConnection = (HttpURLConnection)url.openConnection();            // 设置User-Agent            httpURLConnection.setRequestProperty("User-Agent", "Net");            // 设置续传开始            httpURLConnection.setRequestProperty("Range", "bytes=" + nPos + "-");            // 获取输入流            bis = new BufferedInputStream(httpURLConnection.getInputStream());                       rndFile = new RandomAccessFile(filePath + "\\" + fileName, "rw");            rndFile.seek(nPos);            int i = 0;            while ((size = bis.read(buf)) != -1) {                //if (i > 500) break;                               rndFile.write(buf, 0, size);                                i++;            }            System.out.println("i=" + i);            httpURLConnection.disconnect();        } catch (Exception e) {            // TODO: handle exception            e.printStackTrace();        }    }     public static long getRemoteFileSzie(String url) {        long size = 0;        try {            HttpURLConnection httpUrl = (HttpURLConnection)(new URL(url)).openConnection();            size = httpUrl.getContentLength();            httpUrl.disconnect();                   } catch (Exception e) {            // TODO: handle exception            e.printStackTrace();        }        return size;    }}

参考:

转载于:https://my.oschina.net/xunzhizhe/blog/602453

你可能感兴趣的文章
linu下 php+nginx+mysql安装配置
查看>>
【轻松一刻】那些让我们惊叹不已的唯美GIF动态图片
查看>>
Html.ActionLink
查看>>
Qt事件处理(二)
查看>>
Baruwa 1.1.2 发布,邮件监控系统
查看>>
C# 的关键字系列(4 of n)
查看>>
在获取textbox的时候 如果要转换为int的 可能会出错 如果为空
查看>>
Monkey Studio IDE | The way IDEs should be
查看>>
处理散列冲突的方法
查看>>
「Linux」Linux下根据CET听力文件关键字和lcr时间对mp3进行剪辑分割
查看>>
C/C++通过WMI和系统API函数获取获取系统硬件配置信息(转)
查看>>
浅谈SQL Server中的三种物理连接操作
查看>>
浅谈Redis数据库的键值设计(转)
查看>>
Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能
查看>>
linux中的文件结构
查看>>
汇编学习(3)寄存器
查看>>
CSS quotes 属性
查看>>
Visual Studio统计有效代码行数
查看>>
分享python 元组排序知识点
查看>>
django 获取系统当前时间 和linux 系统当前时间不一致 问题处理。
查看>>