java实现文件的断点续传:

依赖:

<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>

前端实现:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
<script type="text/javascript" src="js/jquery-1.8.3.min.js" ></script>
</head>
<body>
<div class="row">
<label for="fileToUpload">请选择需要上传的文件</label>
<input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();" multiple/>
</div> <div class="row">
<button onclick="uploadFiles()">上传</button>
<button onclick="pauseUpload()">暂停</button>
&nbsp;<label id="progressNumber"></label>
</div>
<div id="fileFrame"></div>
<div id="msg" style="max-height: 400px; overflow:auto;min-height: 100px;">
</div>
<br>
<div><h6>支持批量,支持断点续传</h6></div>
</body> <script>
var msg = null;
var paragraph = 1024*1024*2; //每次分片传输文件的大小 2M
var blob = null;// 分片数据的载体Blob对象
var fileList = null; //传输的文件
var uploadState = 0; // 0: 无上传/取消, 1: 上传中, 2: 暂停 //初始化消息框
function init(){
msg = document.getElementById("msg");
}
function uploadFiles(){
//将上传状态设置成1
uploadState = 1;
if(fileList.files.length>0){
for(var i = 0; i< fileList.files.length; i++){
var file = fileList.files[i];
uploadFileInit(file,i);
}
}else{
msg.innerHTML = "请选择上传文件!";
}
}
/**
* 获取服务器文件大小,开始续传
* @param file
* @param i
*/
function uploadFileInit(file,i){
if(file){
var startSize = 0;
var endSize = 0;
var date = file.lastModifiedDate;
var lastModifyTime = date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate()+"-"
+date.getHours()+"-"+date.getMinutes()+"-"+date.getSeconds()
//获取当前文件已经上传大小
jQuery.post("http://localhost:8084/crm/file/getChunkedFileSize",
{"fileName":encodeURIComponent(file.name),"fileSize":file.size,"lastModifyTime":lastModifyTime,"chunkedFileSize":"chunkedFileSize"},
function(data){
if(data != -1){
endSize = Number(data);
}
uploadFile(file,startSize,endSize,i); }); }
}
/**
* 分片上传文件
*/
function uploadFile(file,startSize,endSize,i) {
var date = file.lastModifiedDate;
var lastModifyTime = date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate()+"-"
+date.getHours()+"-"+date.getMinutes()+"-"+date.getSeconds()
var reader = new FileReader();
reader.onload = function loaded(evt) {
// 构造 XMLHttpRequest 对象,发送文件 Binary 数据
var xhr = new XMLHttpRequest();
xhr.sendAsBinary = function(text){
var data = new ArrayBuffer(text.length);
var ui8a = new Uint8Array(data, 0);
for (var i = 0; i < text.length; i++) ui8a[i] = (text.charCodeAt(i) & 0xff);
this.send(ui8a);
} xhr.onreadystatechange = function(){
if(xhr.readyState==4){
//表示服务器的相应代码是200;正确返回了数据
if(xhr.status==200){
//纯文本数据的接受方法
var message=xhr.responseText;
message = Number(message);
uploadProgress(file,startSize,message,i);
} else{
msg.innerHTML = "上传出错,服务器相应错误!";
}
}
};//创建回调方法
xhr.open("POST",
"http://localhost:8084/crm/file/appendUpload2Server/"+"?"+"fileName="+encodeURIComponent(file.name)+"&fileSize="+file.size+"&lastModifyTime="+lastModifyTime
,false);
xhr.overrideMimeType("application/octet-stream;charset=utf-8");
xhr.sendAsBinary(evt.target.result);
};
if(endSize < file.size){
//处理文件发送(字节)
startSize = endSize;
if(paragraph > (file.size - endSize)){
endSize = file.size;
}else{
endSize += paragraph ;
}
if (file.webkitSlice) {
//webkit浏览器
blob = file.webkitSlice(startSize, endSize);
}else
blob = file.slice(startSize, endSize);
reader.readAsBinaryString(blob);
}else{
document.getElementById('progressNumber'+i).innerHTML = '100%';
}
} //显示处理进程
function uploadProgress(file,startSize,uploadLen,i) {
var percentComplete = Math.round(uploadLen * 100 / file.size);
document.getElementById('progressNumber'+i).innerHTML = percentComplete.toString() + '%';
//续传
if(uploadState == 1){
uploadFile(file,startSize,uploadLen,i);
}
} /*
暂停上传
*/
function pauseUpload(){
uploadState = 2;
} /**
* 选择文件之后触发事件
*/
function fileSelected() {
fileList = document.getElementById('fileToUpload');
var length = fileList.files.length;
var frame = document.getElementById('fileFrame');
for(var i=0; i<length; i++){
file = fileList.files[i];
if(file){
var fileSize = 0;
if (file.size > 1024 * 1024)
fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
else
fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
var nameDiv = document.createElement("div");
nameDiv.setAttribute("id","fileName"+i);
nameDiv.innerHTML='Name: ' + file.name;
var sizeDiv = document.createElement("div");
sizeDiv.setAttribute("id","fileSize"+i);
sizeDiv.innerHTML='fileSize: ' + fileSize;
var typeDiv = document.createElement("div");
typeDiv.setAttribute("id","progressNumber"+i);
typeDiv.innerHTML='';
}
frame.appendChild(nameDiv);
frame.appendChild(sizeDiv);
frame.appendChild(typeDiv);
}
}
</script>
</html>

java后端工具类:

package com.zhl.push.utils;

import org.omg.IOP.Encoding;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile; /**
* @Author
* @ClassName ImgDdUploadUtil
* @Description TODO
* @Date 2018/11/9 15:46
* @Version 1.0
*/
public class ImgDdUploadUtil {
/**
* 获取已上传的文件大小
*
* @param request
* @param
*/
public static Long getChunkedFileSize(HttpServletRequest request) {
//存储文件的路径,根据自己实际确定
String currentFilePath = "E:\\front\\fileUpload\\tinyImgUpload-master\\20181109\\";
// PrintWriter print = null;
try {
request.setCharacterEncoding("utf-8");
// print = response.getWriter();
String fileName = new String(request.getParameter("fileName").getBytes("ISO-8859-1"), "UTF-8");
String lastModifyTime = request.getParameter("lastModifyTime");
File file = new File(currentFilePath + fileName + "." + lastModifyTime);
if (file.exists()) {
return file.length();
} else {
return -1L;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
} /**
* 断点文件上传 1.先判断断点文件是否存在 2.存在直接流上传 3.不存在直接新创建一个文件 4.上传完成以后设置文件名称
*/
public static Long appendUpload2Server(HttpServletRequest request) {
try {
request.setCharacterEncoding("utf-8");
String fileSize = request.getParameter("fileSize");
// long totalSize = StringUtil.toLong(fileSize);
Long totalSize = 0L;
if (fileSize != null && !fileSize.equals("")) {
totalSize = Long.valueOf(fileSize);
}
RandomAccessFile randomAccessfile = null;
long currentFileLength = 0;// 记录当前文件大小,用于判断文件是否上传完成
String currentFilePath = "E:\\front\\fileUpload\\tinyImgUpload-master\\20181109";// 记录当前文件的绝对路径 String fileName = new String(request.getParameter("fileName").getBytes("UTF-8"), "UTF-8");
String lastModifyTime = request.getParameter("lastModifyTime"); String filela = fileName.substring(fileName.lastIndexOf("."), fileName.length());//文件后缀
String filef = fileName.substring(0, fileName.lastIndexOf("."));//文件前缀 // File file = new File(currentFilePath+fileName+"."+lastModifyTime); File file = new File(currentFilePath+"/" + filef +"_"+ lastModifyTime + filela);
// 存在文件
if (file.exists()) {
randomAccessfile = new RandomAccessFile(file, "rw");
} else {
// 不存在文件,根据文件标识创建文件
randomAccessfile = new RandomAccessFile(currentFilePath+"/" + filef +"_"+ lastModifyTime + filela, "rw");
}
// 开始文件传输
InputStream in = request.getInputStream();
randomAccessfile.seek(randomAccessfile.length());
byte b[] = new byte[1024];
int n;
while ((n = in.read(b)) != -1) {
Thread.sleep(1000);
randomAccessfile.write(b, 0, n);
} currentFileLength = randomAccessfile.length(); // 关闭文件
closeRandomAccessFile(randomAccessfile);
randomAccessfile = null;
// 整个文件上传完成,修改文件后缀
// if (currentFileLength == totalSize) {
// File oldFile = new File(currentFilePath + fileName + "." + lastModifyTime);
// File newFile = new File(currentFilePath + fileName);
// if (!oldFile.exists()) {
// return -1L;//重命名文件不存在
// }
// if (newFile.exists()) {// 如果存在形如test.txt的文件,则新的文件存储为test+当前时间戳.txt, 没处理不带扩展名的文件
// String newName = fileName.substring(0, fileName.lastIndexOf("."))
// + System.currentTimeMillis() + "."
// + fileName.substring(fileName.lastIndexOf(".") + 1);
// newFile = new File(currentFilePath + newName);
// }
// if (!oldFile.renameTo(newFile)) {
// oldFile.delete();
// }
//
// }
return currentFileLength; } catch (Exception e) {
e.printStackTrace();
}
return null;
} /**
* 关闭随机访问文件
*
* @param
*/
public static void closeRandomAccessFile(RandomAccessFile rfile) {
if (null != rfile) {
try {
rfile.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

Controller 层:

@RestController
@RequestMapping("/file")
public class FileUpload { @RequestMapping("/getChunkedFileSize")
//requestParam要写才知道是前台的那个数组
public Long getChunkedFileSize(HttpServletRequest request){
Long chunkedFileSize = ImgDdUploadUtil.getChunkedFileSize(request);
return chunkedFileSize;
} @RequestMapping("/appendUpload2Server")
//requestParam要写才知道是前台的那个数组
public Long appendUpload2Server(HttpServletRequest request){
Long aLong = ImgDdUploadUtil.appendUpload2Server(request);
return aLong;
}
}

java实现文件的断点续传的更多相关文章

  1. 用java实现文件的断点续传并发下载

    需求: 支持文件批量下载.现在有很多小图片需要批量下载,不希望在服务器打包下载. 支持大文件断点下载.比如下载10G的文件. PC端全平台支持.Windows,macOS,Linux 全浏览器支持.i ...

  2. java实现文件的断点续传的下载

    java的断点续传是基于之前java文件下载基础上的功能拓展 首先设置一个以线程ID为名的下载进度文件, 每一次下载的进度会保存在这个文件中,下一次下载的时候,会根据进度文件里面的内容来判断下载的进度 ...

  3. java+大文件断点续传

    用JAVA实现大文件上传及显示进度信息 ---解析HTTP MultiPart协议 (本文提供全部源码下载,请访问 https://github.com/1269085759/up6-jsp-mysq ...

  4. JAVA大文件上传断点续传解决方案

    javaweb上传文件 上传文件的jsp中的部分 上传文件同样可以使用form表单向后端发请求,也可以使用 ajax向后端发请求 1.通过form表单向后端发送请求 <form id=" ...

  5. H5+JAVA的文件上传,断点续传

    这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...

  6. java多线程下载和断点续传

    java多线程下载和断点续传,示例代码只实现了多线程,断点只做了介绍.但是实际测试结果不是很理想,不知道是哪里出了问题.所以贴上来请高手修正. [Java]代码 import java.io.File ...

  7. HTTP文件上传服务器-支持超大文件HTTP断点续传的实现办法

    最近由于笔者所在的研发集团产品需要,需要支持高性能的大文件http上传,并且要求支持http断点续传.笔者在以前的博客如何实现支持大文件的高性能HTTP文件上传服务器已经介绍了实现大文件上传的一些基本 ...

  8. java大文件上传解决方案

    最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...

  9. java+大文件上传解决方案

    众所皆知,web上传大文件,一直是一个痛.上传文件大小限制,页面响应时间超时.这些都是web开发所必须直面的. 本文给出的解决方案是:前端实现数据流分片长传,后面接收完毕后合并文件的思路. 实现文件夹 ...

随机推荐

  1. anaconda常用操作汇总

    (1)设置国内(清华)镜像 # 添加Anaconda的TUNA镜像conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/an ...

  2. SQLServer之修改索引

    使用SSMS数据库管理工具修改索引 使用表设计器修改索引 表设计器可以修改任何类型的索引,修改索引的步骤相同,本示例为修改唯一非聚集索引. 1.连接数据库,选择数据库,选择数据表->右键点击表- ...

  3. SQLServer之CHECK约束

    CHECK约束添加规则 1.CHECK 约束用于限制列中的值的范围. 2.Check约束通过逻辑表达式来判断数据的有效性,用来限制输入一列或多列的值的范围,在列中更新数据时,所要输入的内容必须满足Ch ...

  4. Python基础——7面向对象高级编程

    实例与类动态添加方法 实例添加属性: def Student(object): pass s = Student() s.name = ‘syz’ 实例添加方法 from types import M ...

  5. Cloudera Manager(CDH5)内部结构、功能包括配置文件、目录位置等

    1. 相关目录 /var/log/cloudera-scm-installer : 安装日志目录./var/log/* : 相关日志文件(相关服务的及CM的)./usr/share/cmf/ : 程序 ...

  6. js 页面history.back()返回上一页,ios 不重新加载ready的解决办法

    参考自 http://blog.csdn.net/hbts_901111zb/article/details/76691900 项目中,主页面有很多输入字段,当由主页跳转到子页面, 将子页面的字段 s ...

  7. web框架开发-Django模型层(2)-多表操作

    很重要,都是精华 多表关系模型 一对一 一旦确定表关系是一对一,在两张表中的任意一张表中建立关联字段+Unique 一对多 一旦确定表关系是一对多,创建关联字段在多的表中 多对多 一旦确定表关系是多对 ...

  8. pydensecrf的使用

    参考:https://github.com/lucasb-eyer/pydensecrf 1.使用 对于图像来说,最简单的使用该库的方法是使用DenseCRF2D类: import numpy as ...

  9. Exp6 信息搜集与漏洞扫描 20165110

    Exp6 信息搜集与漏洞扫描 20165110 一.实践目标 掌握信息搜集的最基础技能与常用工具的使用方法. 二.实践内容 (1)各种搜索技巧的应用 (2)DNS IP注册信息的查询 (3)基本的扫描 ...

  10. 基于SpringBoot搭建应用开发框架(二) —— 登录认证

    零.前言 本文基于<基于SpringBoot搭建应用开发框架(一)——基础架构>,通过该文,熟悉了SpringBoot的用法,完成了应用框架底层的搭建. 在开始本文之前,底层这块已经有了很 ...