JAVA springboot 大文件分断极速上传带上传进度条

  • 效果图

项目部分架构为html+js+springboot+springMVC

因为没有考虑周到,前期开发有试用WEB文件简单上传,WEB文件多线程上传,sevlet文件分断上传+进度条等,虽都成功,但效果差强人意,直到遇见百度的webuploader,这里感谢百度的webuploader插件开源,虽然网上人员对它的吐槽也不少,哈哈。下面正式开始贴上代码

由于这个功能我觉得有必要分享给大家,因为这个功能是半年前写的,现在贴上,写的不好,希望大家少喷

这里主要注意的问题是,CSS或JS引入不生效的问题,可以将它们直接放在JS脚本或CSS脚 本前引入,或注意顺序问题。

这里感谢一个人提供的博客。这里深表感谢。我是把他的代码直接拿过来修改即用的。

webuploader API查阅官网
http://fex.baidu.com/webuploader/doc/index.html

一,首先前端需引入 代码片.

<!--引入CSS-->
<link rel="stylesheet" type="text/css" href="webuploader文件夹/webuploader.css">

<!--引入JS-->
<script type="text/javascript" src="webuploader文件夹/webuploader.js"></script>

下载下面这个uploader.swf,并将它放入你的项目内,我放在了lib文件夹里

java 带进度条文件上传 java大文件上传进度条_java 带进度条文件上传


二,HTML代码

//文件选择按钮
        <div id="uploader1" class="wu-example">
                            <div class="btns">
                                <span id="picker1"></span><span id="showtotalnumspan1"
                                                                style="display: none">您已选择<span
                                    id="showfiletotalnum1"></span>个文件</span>
                                <br>
                            </div>
                        </div>
//进度条面板
<div id="thelist" class="uploader-list" style="display:none;"></div>

//文件上传事件按锯或清除按钮
 <button id="ctlBtn" class="btn btn-default">开始上传</button>
            <button id="" class="btn btn-default" onclick="clearFileData()">全部清空</button>

三,JS部分(重点)
1.初始化Web Uploader

var $btn = $('#ctlBtn'); //此为文件上传按钮
    var $thelist = $('#thelist'); //此为进度条
    var chunkSize = 5 * 1024 * 1024; //此为文件流管道大小,即一次传输5MB字节,意思是分断大小
// HOOK 这个必须要再uploader实例化前面
    WebUploader.Uploader.register({
        'before-send-f ile': 'beforeSendFile',
        'before-send': 'beforeSend'
    }, {
        beforeSendFile: function (file) {
            console.log("beforeSendFile");
            // Deferred对象在钩子回掉函数中经常要用到,用来处理需要等待的异步操作。
            var task = new $.Deferred();
            // 根据文件内容来查询MD5
            uploader.md5File(file).progress(function (percentage) {   // 及时显示进度
                console.log('计算md5进度:', percentage);
                getProgressBar(file, percentage, "MD5", "MD5");
            }).then(function (val) { // 完成
                console.log('md5 result:', val);
                file.md5 = val;
                // 模拟用户id
                // file.uid = new Date().getTime() + "_" + Math.random() * 100;
                file.uid = WebUploader.Base.guid();
                // 进行md5判断
                $.post("/fileupdown/checkFileMd5", {uid: file.uid, md5: file.md5},
                    function (data) {
                        console.log(data.status);
                        var status = data.status.value;
                        task.resolve();
                        if (status == 101) {
                            // 文件不存在,那就正常流程
                        } else if (status == 100) {
                            // 忽略上传过程,直接标识上传成功;
                            //uploader.skipFile(file);
                            //file.pass = true;
                        } else if (status == 102) {
                            // 部分已经上传到服务器了,但是差几个模块。
                            file.missChunks = data.data;
                        }
                    });
            });
            return $.when(task);
        },
        beforeSend: function (block) {
            console.log("block")
            var task = new $.Deferred();
            var file = block.file;
            var missChunks = file.missChunks;
            var blockChunk = block.chunk;
            console.log("当前分块:" + blockChunk);
            console.log("missChunks:" + missChunks);
            if (missChunks !== null && missChunks !== undefined && missChunks !== '') {
                var flag = true;
                for (var i = 0; i < missChunks.length; i++) {
                    if (blockChunk == missChunks[i]) {
                        console.log(file.name + ":" + blockChunk + ":还没上传,现在上传去吧。");
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    task.reject();
                } else {
                    task.resolve();
                }
            } else {
                task.resolve();
            }
            return $.when(task);
        }
    });

 // 实例化
    var uploader1 = WebUploader.create({
        pick:
            {
                id: '#picker1',
                label: '选择文件',
                multiple: true,
                // 不同功能的上传按钮初始化赋值
                webkitdirectory: false
            },
        formData: {
            uid: 0,
            md5: '',
            chunkSize: chunkSize
        },
        //dnd: '#dndArea',
        //paste: '#uploader',
        //fileVal: 'fileFolder',

        swf: 'js/Uploader.swf',
        chunked: true,
        chunkSize: chunkSize, // 字节 1M分块
        threads: 3,
        server: '/fileupdown/uploadFile',
        auto: false,
        compress: false,//不压缩图片

        accept:null,
        // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
        disableGlobalDnd: true,
        fileNumLimit: 1024,
        fileSizeLimit: 1024 * 1024 * 1024,    // 200 M
        fileSingleSizeLimit: 1024 * 1024 * 1024    // 50 M
    });
var arr = "";//随机码
    var totalFileNum1 = 0;
    var allurls1 = new Array();
    var goOne = true;
    // 当有文件被添加进队列的时候
    uploader1.on('fileQueued', function (file) {
        if (goOne) {
            $("#uploader").hide();
            goOne = false;
        }
        allurls1[totalFileNum1] = file.name;
        totalFileNum1++;
        console.log("fileQueued");
        $thelist.append('<div id="' + file.id + '" class="item">' +
            '<h6 class="info">' + file.name + '</h6>' +
            '<p class="state">等待上传...</p>' +
            '</div>');
        $("#showfiletotalnum1").html(totalFileNum1);
        $("#showtotalnumspan1").show();
    });


    //当某个文件的分块在发送前触发,主要用来询问是否要添加附带参数,大文件在开起分片上传的前提下此事件可能会触发多次。
    uploader1.onUploadBeforeSend = function (obj, data) {
        console.log("onUploadBeforeSend");
        var file = obj.file;
        data.md5 = file.md5 || '';
        data.uid = file.uid;
        data.webkitRelativePath = obj.file.source.source.webkitRelativePath ? obj.file.source.source.webkitRelativePath : '';
        data.orderNo = $("#orderno").val().trim();
        data.salor = $("#salorid").val();
        data.projectName = $("#projectno").val().trim();
        data.fileNames = allurls1;
        data.name = file.name;
        data.saveFolderName = $("#folderselect").val();
        data.randomNum = arr;
    };
    // 上传中
    uploader1.on('uploadProgress', function (file, percentage) {
        getProgressBar(file, percentage, "FILE", "上传进度");
    });
    // 上传返回结果
    uploader1.on('uploadSuccess', function (file) {
        var text = '已上传';
        if (file.pass) {
            text = "文件妙传功能,文件已上传。"
        }
        $('#' + file.id).find('p.state').text(text);
    });
    uploader1.on('uploadError', function (file) {
        $('#' + file.id).find('p.state').text('上传出错');
    });
    uploader1.on('uploadComplete', function (file) {
        // 隐藏进度条
        // fadeOutProgress(file, 'MD5');
        $("#" + file.id).hide();
        fadeOutProgress(file, 'FILE');
    });
 var flagg = true;
    var flaggg = false;


    function checkMessageBeforeUpload() {
        window.parent.document.getElementById('coverbehidepage').style.display = "block";
        var salorid = $("#salorid").val();
        var orderno = $("#orderno").val().trim();
        var projecto = $("#projectno").val().trim();
        var filePathName = "";
        var fileName = "";
        var reg = new RegExp(/^[A-Z]{5}[0-9]{8}[A-Z]{2}[0-9]{2}$/g);
        var filesaveselect = $('input[name="filesaveselect"]:checked').val();
        var url = "";
        var formData = new FormData();
        formData.append('orderNo', $("#orderno").val());
        formData.append('salor', $("#salorid").val());
        // if (typeof (filesaveselect) == "undefined") {
        //     if (totalFileNum1 != 0) {
        //         $("#folderselect").val("");
        //         showfolderdiv();
        //         $("#listshow").removeAttr("checked");
        //         $("#foldershow").prop("checked", 'checked');
        //         $("#listdiv").attr("style", "display:none;")
        //         $("#folderdiv").attr("style", "display:block;")
        //         alert("您没有指定文件夹,系统将默认存放在以订单为名和目录下!");
        //         window.parent.document.getElementById('coverbehidepage').style.display="none";
        //     }
        // } else {
        //     $("#folderselect").val(filesaveselect);
        //     if (reg.test(filesaveselect)) {
        //         $("#folderselect").val("");
        //     }
        // }
        if (salorid == "" || salorid == null) {
            alert("请选择业务人员!");
            window.parent.document.getElementById('coverbehidepage').style.display = "none";
            flagg = false;
            clearUploder()
            return false;
        }
        if (orderno == "") {
            flagg = false;
            clearUploder()
            alert("请填写订单编号!");
            window.parent.document.getElementById('coverbehidepage').style.display = "none";
            return false;
        }
        if (projecto == "") {
            alert("请填写项目名称!");
            window.parent.document.getElementById('coverbehidepage').style.display = "none";
            flagg = false;
            clearUploder()
            return false;
        }
        $("#folderselect").val(filesaveselect);
        if (totalFileNum != 0) {
            for (var i = 0; i < allurls.length; i++) {
                var index = allurls[i].lastIndexOf('/');
                var centerurl = allurls[i].substr(0, index);
                if (allurls[i].indexOf(",") == -1 && centerurl.indexOf(".") == -1) {
                    filePathName += allurls[i] + ",";
                } else {
                    if (allurls[i].indexOf(",") != -1) {
                        alert("您选择的文件夹名含有,符号,如:" + allurls[i]);
                        window.parent.document.getElementById('coverbehidepage').style.display = "none";
                        flagg = false;
                        clearUploder()
                        return false;
                    } else if (centerurl.indexOf(".") != -1) {
                        alert("您选择的文件夹名含有.符号,如:" + allurls[i]);
                        window.parent.document.getElementById('coverbehidepage').style.display = "none";
                        flagg = false;
                        clearUploder()
                        return false;
                    }
                }
            }
            url = "/fileupdown/checkmessagefolder";
            formData.append('filePathName', filePathName);
        } else if (totalFileNum1 != 0) {
            for (var i = 0; i < allurls1.length; i++) {
                if (allurls1[i].indexOf(".") != -1) {
                    fileName += allurls1[i] + ",";
                } else {
                    alert("文件名必须要有扩展名,如:" + allurls1[i] + "就没有扩展名!");
                    window.parent.document.getElementById('coverbehidepage').style.display = "none";
                    flagg = false;
                    clearUploder()
                    return false;
                }
                if (allurls1[i].indexOf(",") != -1) {
                    alert("文件名不能有,符号,如:" + allurls1[i]);
                    window.parent.document.getElementById('coverbehidepage').style.display = "none";
                    flagg = false;
                    clearUploder()
                    return false;
                }
            }
            url = "/fileupdown/checkmessage";
            formData.append('filePathName', fileName);
        } else {
            alert("上传前请选择文件!")
            window.parent.document.getElementById('coverbehidepage').style.display = "none";
            flagg = false;
            clearUploder()
            return false;
        }
        if (flagg) {
            window.parent.document.getElementById('coverbehidepage').style.display = "block";
            //第一步,checkmessage
            $.ajax({
                data: formData,
                type: "POST",
                url: url,
                async: true,
                cache: false,
                contentType: false,
                processData: false,
                success: function (msg) {
                    window.parent.document.getElementById('coverbehidepage').style.display = "none";
                    if (msg != '"OK"') {
                        alert(msg);
                        flaggg = false;
                        clearUploder()
                        return flaggg;
                    } else {
                        flaggg = true;
                        return flaggg;
                    }
                },
                error: function (msg) {
                    window.parent.document.getElementById('coverbehidepage').style.display = "none";
                    alert("查询失败");
                    flaggg = false;
                    clearUploder()
                    return flaggg;

                }
            });
        }
        window.parent.document.getElementById('coverbehidepage').style.display = "none";
    }

    //url = "/fileupdown/checkmessage";
    function saveData() {
        var formData = new FormData();
        formData.append('filePathName', $("#filePathName").val());
        formData.append('orderNo', $("#orderno").val());
        formData.append('salor', $("#salorid").val());
        formData.append('projectName', $("#projectno").val().trim());
        formData.append('random8', arr);
        formData.append('filedescribtion', $("#filedescribtion").val());
        formData.append('remark', $("#remark").val());
        formData.append('saveFolderName', $("#folderselect").val());
        if (totalFileNum != 0) {
            formData.append('filePathNames', allurls);
            $.ajax({
                data: formData,
                type: "POST",
                url: "/fileupdown/saveFolderMessage",
                async: true,
                cache: false,
                contentType: false,
                processData: false,
                success: function (msg) {

                },
                error: function (msg) {
                    alert("插入数据失败")
                    alert(msg)
                    console.log(msg)
                }
            });
        } else if (totalFileNum1 != 0) {
            formData.append('filePathNames', allurls1);
            $.ajax({
                data: formData,
                type: "POST",
                url: "/fileupdown/saveFileMessage",
                async: true,
                cache: false,
                contentType: false,
                processData: false,
                success: function (msg) {

                },
                error: function (msg) {
                }
            });
        }

    }

    //文件加进去时校验
    uploader1.on('filesQueued', function (file) {
        checkMessageBeforeUpload();
        test();
    });
uploader1.on('uploadFinished', function (file) {
        saveData();
        $("#coverbehidepage1").hide();
        window.parent.document.getElementById('coverbehidepageLeft').style.display = "none";
        window.parent.document.getElementById('coverbehidepageTop').style.display = "none";
        window.parent.document.getElementById('coverbehidepage').style.display = "none";
        $("#thelist").hide();
        clearFileData();
        alert("上传成功!")
    });

    $btn.on('click', function () {
        var salorid = $("#salorid").val();
        var orderno = $("#orderno").val().trim();
        var projecto = $("#projectno").val().trim();
        var reg = new RegExp(/^[A-Z]{5}[0-9]{8}[A-Z]{2}[0-9]{2}$/g);
        var filesaveselect = $('input[name="filesaveselect"]:checked').val();
        if (typeof (filesaveselect) == "undefined") {
            if (totalFileNum1 != 0) {
                $("#folderselect").val("");
                $("#listshow").removeAttr("checked");
                $("#foldershow").prop("checked", 'checked');
                $("#listdiv").attr("style", "display:none;")
                $("#folderdiv").attr("style", "display:block;")
                alert("您没有指定文件夹,系统将默认存放在以订单为名和目录下!");
            }
        } else {
            $("#folderselect").val(filesaveselect);
            if (reg.test(filesaveselect)) {
                $("#folderselect").val("");
            }
        }
        if (salorid == "" || salorid == null) {
            alert("请选择业务人员!");
            flagg = false;
            clearFileData()
            return false;
        }
        if (orderno == "") {
            flagg = false;
            clearFileData()
            alert("请填写订单编号!");
            return false;
        }
        if (projecto == "") {
            alert("请填写项目名称!");
            flagg = false;
            clearFileData()
            return false;
        }
        if (totalFileNum1 == 0 && totalFileNum == 0) {
            alert("上传前请选择需要上传的文件或文件夹!");
            return false;
        }
        $("#folderselect").val(filesaveselect);
        if (flaggg) {
            $("#coverbehidepage1").show();//遮罩层开启
            window.parent.document.getElementById('coverbehidepageLeft').style.display = "block";
            window.parent.document.getElementById('coverbehidepageTop').style.display = "block";
            $("#thelist").show();
            //第二步,saveMessageandFileStore
            if (totalFileNum1 != 0) {
                uploader1.upload();
            } else if (totalFileNum != 0) {
                uploader.upload();
            } else if (totalFileNum1 == 0 && totalFileNum == 0) {
                alert("上传前请选择需要上传的文件或文件夹!");
                return false;
            }
        } else {
            return false;
        }
    })
  /**
     *  生成进度条封装方法
     * @param file 文件
     * @param percentage 进度值
     * @param id_Prefix id前缀
     * @param titleName 标题名
     */
    function getProgressBar(file, percentage, id_Prefix, titleName) {
        var $li = $('#' + file.id), $percent = $li.find('#' + id_Prefix + '-progress-bar');
        // 避免重复创建
        if (!$percent.length) {
            $percent = $('<div id="' + id_Prefix + '-progress" class="progress progress-striped active">' +
                '<div id="' + id_Prefix + '-progress-bar" class="progress-bar" role="progressbar" style="width: 0%">' +
                '</div>' +
                '</div>'
            ).appendTo($li).find('#' + id_Prefix + '-progress-bar');
        }
        var progressPercentage = (percentage * 100).toFixed(2) + '%';
        $percent.css('width', progressPercentage);
        $percent.html(titleName + ':' + progressPercentage);
    }

    /**
     * 隐藏进度条
     * @param file 文件对象
     * @param id_Prefix id前缀
     */
    function fadeOutProgress(file, id_Prefix) {
        $('#' + file.id).find('#' + id_Prefix + '-progress').fadeOut();
    }

    function clearUploder() {
        $("#innerfolderdiv").html("");
        if($("#salorid").val()=="" || $("#orderno").val()=="") {
            $("#urltbody ").html("<tr><td colspan='7'>暂无数据</td></tr>")
            $("#foldershow").removeAttr("checked");
            $("#listshow").prop("checked", 'checked');
            $("#listdiv").attr("style", "display:block;")
            $("#folderdiv").attr("style", "display:none;")
        }

        allurls = new Array();
        allurls1 = new Array();
        arr = "";
        $("#uploaddatetime").val(today());
        flagg = true;
        flaggg = false;
        goOne1 = true;
        goOne = true;
        $("#uploader1").show();
        $("#uploader").show();
        totalFileNum = 0;
        totalFileNum1 = 0;
        $("#thelist").html("");
        $("#showfiletotalnum").html("");
        $("#showtotalnumspan").hide();
        $("#thelist1").html("");
        $("#showfiletotalnum1").html("");
        $("#showtotalnumspan1").hide();
        uploader.reset();
        uploader1.reset();
    }

    function clearFileData1() {
        allurls = new Array();
        allurls1 = new Array();
        arr = "";
        flagg = true;
        flaggg = false;
        goOne1 = true;
        goOne = true;
        totalFileNum = 0;
        totalFileNum1 = 0;
        $("#thelist").html("");
        $("#showfiletotalnum").html("");
        $("#showtotalnumspan").hide();
        $("#thelist1").html("");
        $("#showfiletotalnum1").html("");
        $("#showtotalnumspan1").hide();
        uploader.reset();
        uploader1.reset();

    }

2.这里贴上我的css代码

//进度条面板CSS
    #thelist {
        border: 1px solid #9AC0CD;
        width: 800px;
        height: 500px;
        Margin: 2px;
        padding: 3px;
        z-index: 1006;
        background-color: #E0EEEE;
        position: absolute;
        top: 15%;
        left: 12%;
        overflow-y: scroll;
    }

四.这里贴上我的后端application.properties代码

#REDIS配置  这个REDIS我记得在大文件分断上传是用到了,但程序里没有看到,因为时间太久了,也忘了,不过还是贴上

# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=30
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=10000
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=10
# 连接超时时间(毫秒) 10秒
spring.redis.timeout=10000


   #文件上传分片设置(必须)
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB
spring.thymeleaf.reactive.max-chunk-size=5242880  //这个是5MB,一定要与前端那个chunk-size大小一样,前端是传输的大小,后端是接收的大小,不一至话会造成文件流丢失或错误

五,这贴上我的springMVC代码

/**
     * 上传文件
     *
     * @param param
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity uploadFile(MultipartFileParam param, HttpServletRequest request, HttpSession session) throws Exception {
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        UserInfo userInfo = (UserInfo) session.getAttribute("account");
        DownloadView view = new DownloadView();
        if (isMultipart) {
            logger.info("上传文件start。");
            try {
                // 方法1
                //storageService.uploadFileRandomAccessFile(param);
                // 方法2 这个更快点
                view = fileUploadAndDownServ.uploadFileByMappedByteBuffer1(param, userInfo);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("文件上传失败。{}", param.toString());
                throw e;
            }
            logger.info("上传文件end。");
        }
        return ResponseEntity.ok().body("上传成功。");
    }

六,这里贴上我的MultipartFileParam 代码

public class MultipartFileParam implements Serializable {

    private static final long serialVersionUID = 3659911280472399948L;

    private String orderNo;
    private String salor;
    private String webkitRelativePath;
    private String projectName;
    private String filedescribtion;
    private String remark;
    private String modifyreason;
    private String md5;
    private String webkitRelativePaths;
    private String fileNames;
    private String randomNum;
    private  String saveFolderName;
    // 用户id
    private String uid;
    //任务ID
    private String id;
    //总分片数量
    private int chunks;
    //当前为第几块分片
    private int chunk;
    //当前分片大小
    private long size = 0L;
    //文件名
    private String name;
    //分片对象
    private MultipartFile file;
    }
    //GET和SET方法就不贴上了,大家自行补上

七,这里贴上我的业务逻辑代码(重点)

// 保存文件的根目录
    private Path rootPaht;
    
    //这个必须与前端设定的值一致
    @Value("${spring.thymeleaf.reactive.max-chunk-size}")
    private long CHUNK_SIZE;
    
       @Value("${spring.servlet.multipart.location}")
    private String finalDirPath;

 @Transactional(rollbackFor = Exception.class)
    public DownloadView uploadFileByMappedByteBuffer1(MultipartFileParam param, UserInfo userInfo) throws Exception {
        File tmpDir = null;
        String uploadDirPath = finalDirPath;
        String fileName = param.getName();
        //根据业务员订单号设计师看有没有文件夹
        List<FilemanUrl> oldFileUrls = new ArrayList<FilemanUrl>();
        //根据业务员订单号设计师看有没有文件夹
        List<String> urlStr = new ArrayList<String>();
        //根据业务员订单号设计师看有没有文件夹
        List<FileManFileInfo> fileManFileInfo = fileUploadAndDownMapper.isSameOrderNoandOtherMessage(userInfo.getUserName(), param.getOrderNo(), param.getSalor());
        String pointFolder = null;
        boolean f = true;
        if (fileManFileInfo.size() > 0) {  //有文件夹
            oldFileUrls = fileUploadAndDownMapper.findFileUrlByFileInFoData(fileManFileInfo.get(0).getId());
            for (FilemanUrl fu : oldFileUrls) {
                if (param.getSaveFolderName() != null) {
                    if (param.getSaveFolderName() != "" && f) {
                        if (fu.getLogur1().contains("/" + param.getSaveFolderName() + "/")) {
                            pointFolder = fu.getLogur1();
                            f = false;
                        }
                    }
                }
                urlStr.add(fu.getLogur1());
            }

            if (pointFolder != null && pointFolder.length() > 0 && !param.getSaveFolderName().equals("")) {//代表为用户指定目录
                int lia = pointFolder.indexOf("/" + param.getSaveFolderName() + "/");
                pointFolder = pointFolder.substring(0, lia + param.getSaveFolderName().length() + 1);
                tmpDir = new File(uploadDirPath + pointFolder);

            } else {
                String oldPath = null;
                Integer pointindex = null;
                String oldsPath = null;
                oldPath = urlStr.get(0);
                pointindex = StringUtils.ordinalIndexOf(oldPath, "/", 5);
                oldsPath = oldPath.substring(0, pointindex + 1);
                tmpDir = new File(uploadDirPath + oldsPath);
            }

        } else {//如果没有文件夹,直接当成新文件全部存.
            tmpDir = new File(uploadDirPath + userInfo.getUserName() + "/" + formateString(new Date()) + "/" + param.getSalor() + "/"
                    + param.getRandomNum() + "/" + param.getOrderNo() + "/");
        }

        File tmpFile = new File(tmpDir, fileName);
        if (fileName != null) {
            if (!tmpDir.exists()) {
                tmpDir.mkdirs();
            }
            RandomAccessFile tempRaf = new RandomAccessFile(tmpFile, "rw");
            FileChannel fileChannel = tempRaf.getChannel();
            //写入该分片数据
            long offset = CHUNK_SIZE * param.getChunk();
            byte[] fileData = param.getFile().getBytes();
            try {
                MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, offset, fileData.length);
                mappedByteBuffer.put(fileData);
                // 释放
                FileMD5Util.freedMappedByteBuffer(mappedByteBuffer);
                fileChannel.close();
                tempRaf.close();
                mappedByteBuffer.clear();

                boolean isOk = checkAndSetUploadProgress(param, uploadDirPath);
                if (isOk) {
                    // boolean flag = renameFile(tmpFile, fileName);
                    System.out.println("upload complete !! 可以删掉CONF文件 fileName");

                    boolean isdeleteconf = deleteFile(uploadDirPath.concat(fileName).concat(".conf"));
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            } finally {
                boolean isdeleteconf1 = deleteFile(uploadDirPath.concat(fileName).concat(".conf"));
            }
        }
        return null;
    }
 /**
     * 上传完成,删除片文件
     *
     * @param fileName 要删除的文件的文件名
     * @return 单个文件删除成功返回true,否则返回false
     */
    private boolean deleteFile(String fileName) throws Exception {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                System.out.println("删除单个文件" + fileName + "成功!");
                return true;
            } else {
                System.out.println("删除单个文件" + fileName + "失败!");
                return false;
            }
        } else {
            System.out.println("删除单个文件失败:" + fileName + "不存在!");
            return false;
        }
    }


 /**
     * 检查并修改文件上传进度
     *
     * @param param
     * @param uploadDirPath
     * @return
     * @throws
     */
    private boolean checkAndSetUploadProgress(MultipartFileParam param, String uploadDirPath) throws IOException {
        String fileName = param.getName();
        File confFile = new File(uploadDirPath, fileName + ".conf");
        RandomAccessFile accessConfFile = new RandomAccessFile(confFile, "rw");
        //把该分段标记为 true 表示完成
        System.out.println("set part " + param.getChunk() + " complete");
        accessConfFile.setLength(param.getChunks());
        accessConfFile.seek(param.getChunk());
        accessConfFile.write(Byte.MAX_VALUE);

        //completeList 检查是否全部完成,如果数组里是否全部都是(全部分片都成功上传)
        byte[] completeList = FileUtils.readFileToByteArray(confFile);
        byte isComplete = Byte.MAX_VALUE;
        for (int i = 0; i < completeList.length && isComplete == Byte.MAX_VALUE; i++) {
            //与运算, 如果有部分没有完成则 isComplete 不是 Byte.MAX_VALUE
            isComplete = (byte) (isComplete & completeList[i]);
            System.out.println("check part " + i + " complete?:" + completeList[i]);
        }

        accessConfFile.close();
        if (isComplete == Byte.MAX_VALUE) {
            stringRedisTemplate.opsForHash().put(Constants.FILE_UPLOAD_STATUS, param.getMd5(), "true");
            stringRedisTemplate.opsForValue().set(Constants.FILE_MD5_KEY + param.getMd5(), uploadDirPath + "/" + fileName);
            return true;
        } else {
            if (!stringRedisTemplate.opsForHash().hasKey(Constants.FILE_UPLOAD_STATUS, param.getMd5())) {
                stringRedisTemplate.opsForHash().put(Constants.FILE_UPLOAD_STATUS, param.getMd5(), "false");
            }
            if (stringRedisTemplate.hasKey(Constants.FILE_MD5_KEY + param.getMd5())) {
                stringRedisTemplate.opsForValue().set(Constants.FILE_MD5_KEY + param.getMd5(), uploadDirPath + "/" + fileName + ".conf");
            }
            return false;
        }
    }

效果图

java 带进度条文件上传 java大文件上传进度条_java 带进度条文件上传_02

-

java 带进度条文件上传 java大文件上传进度条_java 大文件分断上传_03

java 带进度条文件上传 java大文件上传进度条_java uploader.js使用_04