首页 > 编程 > Java > 正文

java实现文件断点续传下载功能

2019-11-26 14:17:54
字体:
来源:转载
供稿:网友

本文实例为大家分享了java断点续传下载的代码,供大家参考,具体内容如下

1. Java代码    

//实现文件下载功能  public String downloadFile(){    File dir = new File(filepath);//获取文件路劲    if(!dir.exists()) {      System.out.println("文件路径错误");      log.debug("文件路径错误");      return "failed";// 判断文件或文件夹是否存在    }     File downloadFile = new File(dir, filename);//在指定目录下查找文件     if(!downloadFile.isFile()){       System.out.println("文件不存在");        log.debug("文件不存在");        return "failed";// 判断文件或文件夹是否存在     }     try {      downloadFileRanges(downloadFile);     } catch(ClientAbortException e){       System.out.println("连接被终止");       log.debug("连接被终止");     } catch (IOException e) {      e.printStackTrace();     }    return null;   }     private void downloadFileRanges(File downloadFile) throws IOException {     // 要下载的文件大小     long fileLength = downloadFile.length();     // 已下载的文件大小     long pastLength = 0;     // 是否快车下载,否则为迅雷或其他     boolean isFlashGet = true;     // 用于记录需要下载的结束字节数(迅雷或其他下载)     long lenEnd = 0;     // 用于记录客户端要求下载的数据范围字串     String rangeBytes = request.getHeader("Range");     //用于随机读取写入文件     RandomAccessFile raf = null;     OutputStream os = null;     OutputStream outPut = null;     byte b[] = new byte[1024];     // 如果客户端下载请求中包含了范围     if (null != rangeBytes)      {      // 返回码 206      response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);      rangeBytes = request.getHeader("Range").replaceAll("bytes=", "");      // 判断 Range 字串模式      if (rangeBytes.indexOf('-') == rangeBytes.length() - 1)       {      // 无结束字节数,为快车      isFlashGet = true;      rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf('-'));      pastLength = Long.parseLong(rangeBytes.trim());      }       else      {      // 迅雷下载      isFlashGet = false;      String startBytes = rangeBytes.substring(0,       rangeBytes.indexOf('-'));      String endBytes = rangeBytes.substring(       rangeBytes.indexOf('-') + 1, rangeBytes.length());      // 已下载文件段      pastLength = Long.parseLong(startBytes.trim());      // 还需下载的文件字节数(从已下载文件段开始)      lenEnd = Long.parseLong(endBytes);      }     }     // 通知客户端允许断点续传,响应格式为:Accept-Ranges: bytes     response.setHeader("Accept-Ranges", "bytes");     // response.reset();     // 如果为第一次下载,则状态默认为 200,响应格式为: HTTP/1.1 200 ok     if (0 != pastLength)     {      // 内容范围字串      String contentRange = "";      // 响应格式      // Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]||[文件的总大小]      if (isFlashGet)      {      contentRange = new StringBuffer("bytes")       .append(new Long(pastLength).toString()).append("-")       .append(new Long(fileLength - 1).toString())       .append("/").append(new Long(fileLength).toString())       .toString();      }      else      {      contentRange = new StringBuffer(rangeBytes).append("/")       .append(new Long(fileLength).toString()).toString();      }      response.setHeader("Content-Range", contentRange);     }     String fileName = getDownloadChineseFileName(filename);     response.setHeader("Content-Disposition",      "attachment;filename=" + fileName + "");     // 响应的格式是:     response.setContentType("application/octet-stream");     response.addHeader("Content-Length", String.valueOf(fileLength));     try     {      os = response.getOutputStream();      outPut = new BufferedOutputStream(os);      raf = new RandomAccessFile(downloadFile, "r");      // 跳过已下载字节      raf.seek(pastLength);      if (isFlashGet)       {      // 快车等      int n = 0;      while ((n = raf.read(b, 0, 1024)) != -1)       {       outPut.write(b, 0, n);      }      }       else      {      // 迅雷等      while (raf.getFilePointer() < lenEnd)      {       outPut.write(raf.read());      }      }      outPut.flush();     }     catch (IOException e)     {      /**      * 在写数据的时候 对于 ClientAbortException 之类的异常      * 是因为客户端取消了下载,而服务器端继续向浏览器写入数据时, 抛出这个异常,这个是正常的。 尤其是对于迅雷这种吸血的客户端软件。      * 明明已经有一个线程在读取 bytes=1275856879-1275877358,      * 如果短时间内没有读取完毕,迅雷会再启第二个、第三个。。。线程来读取相同的字节段, 直到有一个线程读取完毕,迅雷会 KILL      * 掉其他正在下载同一字节段的线程, 强行中止字节读出,造成服务器抛 ClientAbortException。      * 所以,我们忽略这种异常      */     }      finally     {      if(outPut != null)      {       outPut.close();      }      if(raf != null)      {      raf.close();      }     }     }           private String getDownloadChineseFileName(String paramName)    {   String downloadChineseFileName = "";   try   {    downloadChineseFileName = new String(paramName.getBytes("GBK"),     "ISO8859-1");   }   catch (UnsupportedEncodingException e)   {    e.printStackTrace();   }   return downloadChineseFileName;   }           public String getFilepath() {    return filepath;  }  public void setFilepath(String filepath) {    this.filepath = filepath;  }  public String getFilename() {    return filename;  }  public void setFilename(String filename) {    this.filename = filename;  }  public HttpServletRequest getRequest() {   return request;   }   public HttpServletResponse getResponse() {   return response;   }

2. struts部分    

复制代码 代码如下:
<action name="downloadFile" class="downloadFileAction" method="downloadFile">
   <result name="failed" type="redirectAction">showDownloadFileNameList</result>
</action>

3. jsp部分    

复制代码 代码如下:
<td><a href="downloadFile?filename=${fileMap.key }&&filepath=${fileMap.value }">文件下载</a></td>

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表