java实现文件的断点续传

邓维      2022-04-18     798

关键词:

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>
View Code

 

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:frontfileUpload	inyImgUpload-master20181109";
//        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:frontfileUpload	inyImgUpload-master20181109";// 记录当前文件的绝对路径

            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;
    }
}

 

前端实现文件的断点续传

 早就听说过断点续传这种东西,前端也可以实现一下断点续传在前端的实现主要依赖着HTML5的新特性,所以一般来说在老旧浏览器上支持度是不高的 本文通过断点续传的简单例子(前端文件提交+后端PHP文件接收),理解... 查看详情

前端实现文件的断点续传

早就听说过断点续传这种东西,前端也可以实现一下断点续传在前端的实现主要依赖着HTML5的新特性,所以一般来说在老旧浏览器上支持度是不高的本文通过断点续传的简单例子(前端文件提交+后端PHP文件接收),理解其大致的... 查看详情

前端实现文件的断点续传

早就听说过断点续传这种东西,前端也可以实现一下断点续传在前端的实现主要依赖着HTML5的新特性,所以一般来说在老旧浏览器上支持度是不高的本文通过断点续传的简单例子(前端文件提交+后端PHP文件接收),理解其大致的... 查看详情

java实现文件的断点续传和断点下载,有知道的交流下。

java实现文件的断点续传和断点下载,有知道的交流下。参考技术A/**      * 下载服务器已存在的文件      *       * @param request     ... 查看详情

html超大文件上传和断点续传的实现

需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制。 第一步:前端修改由于项目使用的是BJUI前端框架,... 查看详情

断点续传实现

断点续传实现:简单来说应该分为两个角度来看待:1、将要续传的文件2、续传的文件一、将要续传的文件先说说将要续传的文件,既然是续传,那么肯定要有个标识,举例说明一下:  事先准备一个文件,大小是1852... 查看详情

断点续传

早就听说过断点续传这种东西,前端也可以实现一下断点续传在前端的实现主要依赖着HTML5的新特性,所以一般来说在老旧浏览器上支持度是不高的本文通过断点续传的简单例子(前端文件提交+后端PHP文件接收),理解其大致的... 查看详情

用java向hdfs上传文件时,如何实现断点续传

...大小和字节数,然后只上传该文件没有的部分。请问如何实现,最好附上完整代码,分不多,谢谢。@Component("javaLargeFileUploaderServlet")@WebServlet(name="javaLargeFileUploaderServlet",urlPatterns="/javaLargeFileUploaderServlet")publicclassUploadServletextendsHtt... 查看详情

java大文件断点续传

...了Socket通信机制以及JavaIO流两个技术点,具体思路如下:实现思路:1、服:利用ServerSocket搭建服务器,开启相应端口,进行长连接操作2、服:使用ServerSocket.accept()方法进行阻塞,接收客户端请求3、服:每接收到一个Socket就建立... 查看详情

文件下载之断点续传(客户端与服务端的实现)

【转】文件下载之断点续传(客户端与服务端的实现)【转】文件下载之断点续传(客户端与服务端的实现)前面讲了文件的上传,今天来聊聊文件的下载。老规矩,还是从最简单粗暴的开始。那么多简单算简单?多粗暴算粗暴... 查看详情

如何用java实现http断点续传功能

断点设置方法,当有临时文件时,直接在临时文件中读取上次下载中断时的断点位置。没有临时文件,即第一次下载时,重新设置断点。rantmpfile.seek()跳转到一个位置的目的是为了让各个断点存储的位置尽量分开。参考技术A我项... 查看详情

java如何实现大文件分片上传,断点续传和秒传

Java如何实现大文件分片上传,断点续传和秒传引言概念秒传1、什么是秒传2、实现秒传常见做法分片上传1、什么是分片上传2、分片上传的场景断点续传1、什么是断点续传2、应用场景3、实现断点续传的核心逻辑实现思路前置知识... 查看详情

前端js实现文件的断点续传后端php文件接收

http://www.jb51.net/article/94732.htm 查看详情

基于http的文件断点续传实现(代码片段)

基于Http的文件断点续传实现1:断点续传的介绍客户端软件断点续传指的是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如... 查看详情

用网页实现断点续传(http)

...ket通信机制以及JavaIO流两个技术点,具体思路如下: 实现思路:1、服:利用ServerSocket搭建服务器,开启相应端口,进行长连接操作2、服:使用ServerSocket.accept()方法进行阻塞,接收客户端请求3、服:每接收到一个Socket就建立... 查看详情

java实现的断点续传功能

代码中已经加入了注释,需要的朋友可以直接参考代码中的注释。下面直接上功能实现的主要代码: importjava.io.File;importjava.io.FileNotFoundException;importjava.io.IOException;importjava.io.InputStream;importjava.io.RandomAccessFile;importjava.n 查看详情

断点续传下载原理实现

...度动态创建的文件希望能够分段下载HTTP断点续传报文要实现HTTP断点续传必须要简单了解以下几个报文。Accept-Ranges告诉客户端(浏览器..)服务器端支持断点续传 服务器端返回Range客户端告诉服务器端从指定的的位置/范围(这里... 查看详情

文件下载之断点续传(客户端与服务端的实现)

原文:http://www.cnblogs.com/zhaopei/p/download.html 阅读目录 文件下载-服务端使用a标签提供文件下载使用Response.TransmitFile提供文件下载其他方式文件下载文件下载-客户端直接下载异步下载断点续传断点续传(服务端的支持)多线程... 查看详情