用java实现文件的断点续传并发下载
需求:
支持文件批量下载。现在有很多小图片需要批量下载,不希望在服务器打包下载。
支持大文件断点下载。比如下载10G的文件。
PC端全平台支持。Windows,macOS,Linux
全浏览器支持。ie6,ie7,ie8,ie9,ie10,ie11,edge,firefox,chrome,safari
支持文件夹结构下载。不希望在服务器打包,而是直接下载文件夹,下载后在本地文件夹结构和服务器保持一致。
支持从URL中下载文件。
支持JSON数据结构。
说明
用java实现文件的断点续传,使用了HTTP的首部字段实现,在网上看到例子,手动实现一遍,理解其原理,在这记录下
正文
要实现断点续传,要在请求中设置请求开始的位置和结束位置,在HTTP请求中设置RANGE首部字段,之后服务器如果能正常返回,返回206状态码
用java实现的关键点:
1.设置请求的首部字段,使用java的net包
2.在读取资源文件后,要保存文件,从断点处保存,使用RandAccessFile类
3.使用多线程并发的方式进行,如何正确设置起始位置
主要思路就是:
1. 设置文件信息,包括文件所在的URL,文件名,文件保存的路径及文件需要分段下载的次数
2. 下载时,先连接服务器,得到文件的大小,通过服务器响应的首部字段Content-Length获得,得到文件大小后,根据分段下载的次数设置每次开始的位置,结束位置。并创造一个信息临时文件,用来保存每次分段下载的起始位置,用于非第一次下载时,可以直接本地读取起始信息
3. 分段下载根据开始位置,保存在下载文件的合适位置,使用RandAccessFile类的seek()方法定位
文件分块下载代码
<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@page contentType="text/html;charset=UTF-8"%>
<%@page import="down2.*" %>
<%@page import="java.net.URLDecoder" %>
<%@page import="java.net.URLEncoder" %>
<%@page import="org.apache.commons.lang.*" %>
<%@page import="com.google.gson.FieldNamingPolicy" %>
<%@page import="com.google.gson.Gson" %>
<%@page import="com.google.gson.GsonBuilder" %>
<%@page import="com.google.gson.annotations.SerializedName" %>
<%@page import="java.io.*" %>
<% out.clear();
/*
下载数据库中的文件。
更新记录:
2015-05-13 创建
2017-12-09 完善Range协议
*/
String fileName = "网易云音乐.exe";//客户端保存的文件名
String filePath = "d:\\文件校验工具.exe";//路径
fileName = URLEncoder.encode(fileName,"UTF-8");
fileName = fileName.replaceAll("\\+","%20");
response.setContentType("application/octet-stream;charset:utf-8");
response.addHeader("Content-Disposition","attachment;filename=" + fileName);
response.addHeader("Pragma", "No-cache");
response.addHeader("Cache-Control", "No-cache");
response.addHeader("Expires", "0");
//定位文件块索引
File f = new File(filePath);
long fileLen = f.length();
long blockSize = fileLen;//块大小
long blockBegin = 0;
long blockEnd = 0;
RandomAccessFile raf = new RandomAccessFile(filePath,"r");
FileInputStream in = new FileInputStream( raf.getFD() );
String range = request.getHeader("Range");
if(range != null)
{
//清除bytes=
int pos = range.indexOf("=");
if(pos != -1) range = range.substring(pos+1);
/*
1-
-1
0-1
*/
String[] rs = range.split("-");//bytes=10254
//-1
if( StringUtils.isEmpty(rs[0]) )
{
blockSize = Long.parseLong(rs[1]);
in.skip(fileLen - blockSize);
blockEnd = fileLen - 1;
blockBegin = fileLen - blockSize;
}//1-
elseif( StringUtils.isEmpty(rs[1]))
{
blockBegin = Long.parseLong(rs[0]);
in.skip(blockBegin);
blockSize = fileLen - blockBegin;
blockEnd = (blockBegin + blockSize) - 1;
}//1-1
else
{
blockBegin = Long.parseLong(rs[0]);
blockEnd = Long.parseLong(rs[1]);
blockSize = (blockEnd - blockBegin) + 1;
in.skip(blockBegin);
}
}
response.addHeader("Content-Length",Long.toString(blockSize));
response.addHeader("Content-Range",String.format("bytes %d-%d/%d",blockBegin,blockEnd,fileLen) );
byte[] b = newbyte[1048576];//一次读1MB数据,如果服务器内存足够,可适当调大尺寸。
int i = 0;
OutputStream outp = response.getOutputStream();
while((i = in.read(b)) > 0)
{
outp.write(b, 0, i);
}
outp.flush();
in.close();
outp.close();
in = null;
outp = null;
%>
2、文件的保存
文件保存由前端实现。由用户下载前选择文件的下载路径。
3、批量下载
批量下载通过urls参数即可实现。
$("#btn-down-files").click(function (){
if(downer.Config["Folder"]==""){ downer.open_folder();return;}
var urls =[
{ fileUrl:"http://res2.ncmem.com/res/images/ie11.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/up6.1/down.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/firefox.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/edge.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/up6.1/cloud.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/home/w.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/img.png"}
];
downer.app.addUrls(urls);
});
4、自定义下载文件夹名称
基本信息包含了文件所在站点信息,文件本地保存路径,文件名,文件分段下载次数
$("#btn-down-json").click(function (){
if(downer.Config["Folder"]==""){ downer.open_folder();return;}
var fd ={
nameLoc:"图片列表"
, files:[
{ fileUrl:"http://res2.ncmem.com/res/images/ie11.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/up6.1/down.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/firefox.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/edge.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/up6.1/cloud.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/home/w.png"}
,{ fileUrl:"http://res2.ncmem.com/res/images/img.png"}
]
};
downer.app.addJson(fd);
});
5、下载多级目录
//下载多级目录
$("#btn-down-fd").click(function (){
if(downer.Config["Folder"]==""){ downer.open_folder();return;}
var fd ={
nameLoc:"测试文件夹"
, files:[
{ fileUrl:"http://www.ncmem.com/images/ico-ftp.jpg"}
,{ fileUrl:"http://www.ncmem.com/images/ico-up.jpg"}
]
, folders:[
{
nameLoc:"图片1"
, files:[
{ fileUrl:"http://www.ncmem.com/images/ico-ftp.jpg"}
,{ fileUrl:"http://www.ncmem.com/images/ico-up.jpg"}
,{ fileUrl:"http://www.ncmem.com/images/ico-capture.jpg"}
,{ fileUrl:"http://www.ncmem.com/images/ico-imageuploader.gif"}
,{ fileUrl:"http://www.ncmem.com/images/ico-wordpaster.gif"}
]
, folders:[
{
nameLoc:"软件"
, files:[
{ fileUrl:"http://res2.ncmem.com/res/images/edit-file.png"}
]
}
]
}
]
};
downer.app.addJson(fd);
});
网上例子:http://blog.ncmem.com/wordpress/2019/08/28/java批量下载/
用java实现文件的断点续传并发下载的更多相关文章
- java实现文件的断点续传的下载
java的断点续传是基于之前java文件下载基础上的功能拓展 首先设置一个以线程ID为名的下载进度文件, 每一次下载的进度会保存在这个文件中,下一次下载的时候,会根据进度文件里面的内容来判断下载的进度 ...
- java实现文件的断点续传
java实现文件的断点续传: 依赖: <!--文件上传--> <dependency> <groupId>commons-fileupload</groupI ...
- java的文件上传和下载 抄袭别人的.在底部有说明.
=======后续 这里采用的是输出流的方式,我电脑装的是windows系统,测试没有问题,但是当把项目放到Linux系统上跑时,就会出现保存位置错误的情况, 指定的路径就会被当做文件名的一部分保存了 ...
- Java实现文件的上传下载
文件上传,下载的方法: 上传代码 /** * 文件上传.保存 * * @param mapping * @param form * @param request * @param response * ...
- Java 实现文件上传、下载、打包、文件copy、文件夹copy。
文件and文件夹copy package org.test; import java.io.*; public class FileCopy { /** * 复制单个文件 * * @param old ...
- http文件的断点续传和下载
http://www.tuicool.com/articles/ZbyymqJ Content-Disposition:inline; filename= "c501b_01_h264_sd ...
- Java Struts文件上传和下载详解
Struts2文件上传 Struts 2框架提供了内置支持处理文件上传使用基于HTML表单的文件上传.上传一个文件时,它通常会被存储在一个临时目录中,他们应该由Action类进行处理或移动到一个永久的 ...
- JAVA SFTP文件上传、下载及批量下载
JavaJsch 1.jsch官方API查看地址(附件为需要的jar) http://www.jcraft.com/jsch/ 2.jsch简介 JSch(Java Secure Channel)是 ...
- java+超大文件上传与下载
这里先说下spring mvc 遇到的坑,就是如果文件上传时,后端这样写public String file1(HttpServletRequest request),根据request拿到的东西是 ...
随机推荐
- day49—JavaScript阻止浏览器默认行为
转行学开发,代码100天——2018-05-04 今天主要说明一下通过JavaScript对浏览器默认行为的阻止操作.比如右键菜单的行为. 阻止默认行为的语句为: return false; 例如,阻 ...
- Powershell指令集_2
目录 目录 获取证书 Get-Childitem 调用REST API Invoke-RestMethod 选择对象属性 Select-Object 导入模块 Invoke-Expression 路径 ...
- c# WPF——完成一个简单的百度贴吧爬虫客户端
话不多说先上图 爬取10页大概500个帖子大概10s,500页2w多个帖子大概2min,由此可见性能并不是特别好,但是也没有很差. 好了话不多说,我们来一步一步实现这么个简易的客户端. 1.创建项目 ...
- Altium Designer chapter8总结
元件库操作中需要注意如下: (1)原理图库:主要分三部分来完成(绘制元件的符号轮廓.放置元件引脚.设计规则检查). (2)多子件原理图库:操作与原理图库基本相同,就是新建part. (3)PCB封装库 ...
- LeetCode——141 设计链表
题目: 简单说下思路: 用两个指针,一个跑得快,一个跑得慢(例如一个每次前进两步,一个前进一步),这样只要快指针不会撞上NULL(如果遇到了NULL的情况那么必然不存在环),快指针肯定会和慢指针碰面( ...
- C++边双缩点,Redundant Paths 分离的路径
一道比较简单的 关于边双的题,个人感觉难度不大. 求出整个图的边双,根据边双的定义我们可以延伸出 边双的任两个点都有至少两种路径来互相抵达(因为其不存在割边) .不妨将每个边双缩成一个点,样例中的图便 ...
- html5 WebSocket的Js实例教程
详细解读一个简单+ ,附带完整的javascript websocket实例源码,以及实例代码效果演示页面,并对本实例的核心代码进行了深入解读. 从WebSocket通讯三个阶段(打开握手.数据传递. ...
- APM全链路监控--日志收集篇
一.监控的意义: 随着互联网普及的广度和深度,对于项目的监控显得格外重要:无论是web服务器进程.内存.cpu等资源监控,还是爬虫程序请求频率,状态码以及储存结果的监控,都需要一个及时的反馈机制. 二 ...
- [Web 前端] 010 css 常用的边框设置
css 常用边框属性 概览 参数 释义 border u设置边框属性(可以多个) border-color 边框颜色 border-style 边框样式solid 实线,dotted 点状线,dash ...
- [19/05/13-星期一] HTML_head标签 和 body标签_文本标签
一.概念 概念:超文本标记语言 作用:需要将Java在后台根据用户的请求处理结果在浏览器显示给用户.数据已经过来了,但是显示可能比较凌乱,所以html应用而生,就像写作文要加标点看着舒服. 在浏览器中 ...