webuploader工具官网:http://fex.baidu.com/webuploader/

webuploader自行官网下载

博主项目GitHub地址:https://github.com/AnRan-727/webuploader

上传文件按钮Html

<div id="uploader" class="wu-example">
    <!--用来存放文件信息-->
    <div id="thelist" class="uploader-list"></div>
    <div class="btns">
        <div id="picker">选择文件夹</div>
        <button id="ctlBtn" class="btn btn-default">开始上传</button>
    </div>
    <p>
        <span>上传所用时间:</span>
        <span id="useTime">0</span>s
    </p>
</div>

多文件、文件夹分片上传Js

    代码示例:

                注意:此处的webuploader.js文件是经过修改的,原版js不支持选择文件夹

                          在webuploader.js文件中大概4888行处增加代码

                input.attr( 'type', 'file' );
                input.attr( 'name', opts.name );
                input.attr("webkitdirectory", "");//此行为新增的代码
<script type="text/javascript" src="../jquery-3.4.1.js"></script>
<script type="text/javascript" src="../script/multiJs/webuploader.js"></script>
<script type="text/javascript" src="../script/layer/layer.js"></script>
<script>
    var $list = $("#thelist");
    var $btn = $("#ctlBtn");
    var state = 'pending'; // 上传文件初始化
    var timer;
    var fileArray = [];
    var uploader = WebUploader.create({
        // 文件接收服务端。
        server: '/multi/upload',
        pick: '#picker',
        // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
        resize: false,
        duplicate: true,
        chunked: true,
        threads: 5,
        chunkSize: 10485760
    });
    //点击上传之前调用的方法
    uploader.on("uploadStart", function (file) {
        var guid = WebUploader.Base.guid();//上传的文件信息  也就是Controller控制层合并文件的参数
        var paramOb = {"guid": guid,"name":file.source.name,"webkitRelativePath":file.source.source.webkitRelativePath};
        uploader.options.formData.guid = guid;
        fileArray.push(paramOb);
    });
    // 当有文件被添加进队列的时候
    uploader.on('fileQueued', function (file) {
        $list.append('<div id="' + file.id + '" class="item">' +
            '<h4 class="info">' + file.name + '</h4>' +
            '<p class="state">等待上传...</p>' +
            '</div>');
    });
    // 文件上传过程中创建进度条实时显示。
    uploader.on('uploadProgress', function (file, percentage) {
        var $li = $('#' + file.id),
            $percent = $li.find('.progress .progress-bar');
        // 避免重复创建
        if (!$percent.length) {
            $percent = $('<div class="progress progress-striped active">' +
                '<div class="progress-bar" role="progressbar" style="width: 0%">' +
                '</div>' +
                '</div>').appendTo($li).find('.progress-bar');
        }
        $li.find('p.state').text('上传中');
        $percent.css('width', percentage * 100 + '%');
    });
    //文件成功、失败处理
    uploader.on('uploadSuccess', function (file) {
        $('#' + file.id).find('p.state').text('已上传');
    });
    //文件上传出错
    uploader.on('uploadError', function (file) {
        $('#' + file.id).find('p.state').text('上传出错');
    });
    //文件上传完成
    uploader.on('uploadComplete', function (file) {
        $('#' + file.id).find('.progress').fadeOut();
    });
    //所有文件上传完成以后
    uploader.on('uploadFinished', function () {
        var fileAr = JSON.stringify(fileArray);
        console.log(fileAr);
//发送合并请求
        $.get({
            url:"/multi/merge",
            data:{
                "fileArray":fileAr
            },
            success:function (data) {
                layer.msg("上传完成");
            }
        })
    });
    //点击上传时间
    $btn.on('click', function () {
        if (state === 'uploading') {
            uploader.stop();
        } else {
            uploader.upload();
            timer = setInterval(function () {
                var useTime = parseInt($("#useTime").html());
                useTime = useTime + 1;
                $("#useTime").html(useTime);
            }, 1000);
        }
    });
</script>

Controller控制层:

package com.liuyinlong.www.webuploader.webuploader.controller;
 
import com.alibaba.fastjson.JSON;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
 
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
 
/**
 * Created by IntelliJ IDEA.
 * User: AnRan
 * Url: www.liuyinlong.com
 * Date: 2020/7/28
 */
@Controller
public class MultiUploadController {
 
    //该路径可根据项目需求存储到数据库
    //正式文件路径
    @Value("${upload.file.path}")
    private String decryptFilePath;
    //临时文件路径  分片
    @Value("${upload.file.path.temp}")
    private String decryptFilePathTemp;
 
    /**
     * 分片上传文件
     * @param request
     * @param file 文件
     * @param chunks 分片总数
     * @param chunk 现在是第几片
     * @param guid 整个分片文件的guid  当作临时文件路径
     * @return
     * @throws IOException
     */
    @PostMapping("/multi/upload")
    @ResponseBody
    public ResponseEntity<Void> decrypt(HttpServletRequest request, @RequestParam MultipartFile file, Integer chunks, Integer chunk,String guid) throws IOException {
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (isMultipart) {
            if (file != null) {
                if (chunks == null && chunk == null) {
                    chunk = 0;
                }
                File outFile = new File(decryptFilePathTemp + File.separator+guid, chunk + ".part");
                InputStream inputStream = file.getInputStream();
                FileUtils.copyInputStreamToFile(inputStream, outFile);
            }
        }
        return ResponseEntity.ok().build();
    }
 
    /**
     * 合并分片的文件
     * @param fileArray 文件集合  guid分片文件夹 name文件名称 webkitRelativePath文件路径+名称
     *                  [{"guid":"wu_1eeaqpv3af8i1m461iqn3q41m6v9","name":"VMware-workstation-full-14.1.1.28517.exe","webkitRelativePath":"测试文件/VMware-workstation-full-14.1.1.28517.exe"}
     *                  ,{"guid":"wu_1eeaqqqoth351mqt1ki71hua1aao38","name":"Xftp-6.0.0095p.exe","webkitRelativePath":"测试文件/Xftp-6.0.0095p.exe"}
     *                  ,{"guid":"wu_1eeaqqsj34e2t4mcj290h1do23h","name":"bootdemo-0.0.1-SNAPSHOT.jar","webkitRelativePath":"测试文件/测试用的web项目/bootdemo-0.0.1-SNAPSHOT.jar"}
     *                  ,{"guid":"wu_1eeaqqsql99r107116au10cbpl33m","name":"test.war","webkitRelativePath":"测试文件/测试用的web项目/test.war"}
     *                  ,{"guid":"wu_1eeaqqss2n883erh1stsnv0k3o","name":"webdemo.war","webkitRelativePath":"测试文件/测试用的web项目/webdemo.war"}
     *                  ,{"guid":"wu_1eeaqqsu4mcbpbv19mb8rq15h93q","name":"bootdemo-0.0.1-SNAPSHOT - 副本.jar","webkitRelativePath":"测试文件/测试用的web项目/阿萨德/bootdemo-0.0.1-SNAPSHOT - 副本.jar"}]
     * @throws Exception Exception
     */
    @GetMapping("/multi/merge")
    @ResponseBody
    public void byteMergeAll(@RequestParam String fileArray) {
        List<Map<String,String>> listMap = (List<Map<String, String>>) JSON.parse(fileArray);
        for (Map<String, String> stringStringMap : listMap) {
            //获取分片文件路径
            File file = new File(decryptFilePathTemp+File.separator+stringStringMap.get("guid"));
            //判断是否是文件夹
            if (file.isDirectory()) {
                //得到该分片文件夹下的所有分片文件
                File[] files = file.listFiles();
                //判断是否为空
                if (files != null && files.length > 0) {
                    //文件名称
                    String fileName = stringStringMap.get("name");
                    //文件相对路径+名称
                    String webkitRelativePath =stringStringMap.get("webkitRelativePath");
                    //移除路径中的文件名
                    String remove = StringUtils.remove(webkitRelativePath, fileName);
                    //设置路径为 本地目录+文件相对路径
                    String filePath = decryptFilePath +"\\"+remove;
                    File file1 = new File(filePath);
                    if(!file1 .exists()) { //当该文件夹不存在时
                        file1.mkdirs();//创建目录
                    }
                    //创建真实文件
                    File partFile = new File(filePath + File.separator + fileName);
                    try {
                        //合并所有文件分片到真实文件中
                        for (int i = 0; i < files.length; i++) {
                            File s = new File(decryptFilePathTemp+File.separator+stringStringMap.get("guid"), i + ".part");
                            FileOutputStream destTempfos = new FileOutputStream(partFile, true);
                            FileUtils.copyFile(s,destTempfos );
                            destTempfos.close();
                        }
                        //删除文件分片
                        FileUtils.deleteDirectory(file);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注