zoukankan      html  css  js  c++  java
  • WebUploader分片断点上传文件(二)

    写在前面:

      这几天,有去研究一下WebUploader上传文件,前面的博客有记录下使用WebUploader简单上传文件的例子,今天就把分片断点上传的例子也记录下吧,在博客园中,也查看了一些资料,基本上后台处理数据都是用的Servlet,或者是SpringMVC,由于最近的项目一直都是Struts2,所以这里就用Struts2中的action来对数据进行处理,达到分片上传文件的效果。

      

      1.什么是分片上传?

      顾名思义,就是把文件分成一片片,即让一个文件,分割成好几个小文件,然后再上传。这样做的好处是便于上传大文件。

      2.分片上传大致思路:

      1.前台页面,选择文件,点击按钮进行上传。

      2.WebUploader将上传的文件,分割成指定的个数,挨个发送到服务端后台。

      3.服务器接收分割后的小文件,并存储到临时文件夹下

      4.服务器接收分割后的小文件完毕后,前台页面执行上传成功函数。

      5.在上传成功函数中,发送请求到服务器,请求合并小文件为一个整体的文件。

      6.服务器后台对文件进行合并操作,合并完成后删除存储小文件的临时文件。

      了解了分片上传的大致过程,下面直接上demo吧。

      前台页面:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%
        String scheme = request.getScheme();
        String serverName = request.getServerName();
        String contextPath = request.getContextPath();
        int port = request.getServerPort();
    
        //网站的访问跟路径
        String baseURL = scheme + "://" + serverName + ":" + port
                + contextPath;
        request.setAttribute("baseURL", baseURL);
    %>
    <html>
    <head>
        <title>WebUploader文件分片上传简单示例</title>
        <%--引入css样式--%>
        <link href="${baseURL}/webuploader0.1.5/webuploader.css" rel="stylesheet" type="text/css"/>
        <script src="${baseURL}/ligerui2/jquery/jquery-1.9.0.min.js" type="text/javascript"></script>
        <%--引入文件上传插件--%>
        <script type="text/javascript" src="${baseURL}/webuploader0.1.5/webuploader.min.js"></script>
    
        <script type="text/javascript">
    
                $(function(){
                    /*
                    对于uploader的创建,最好等dom元素也就是下面的div创建好之后再创建,因为里面有用到选择文件按钮,
                    不然会创建报错,这是很容易忽视的地方,故这里放到$(function(){}来进行创建*/
                    var uploader = WebUploader.create({
    
                        // swf文件路径
                        swf: '${baseURL}/webuploader0.1.5/Uploader.swf',
                        // 文件接收服务端地址。
                        server: '${baseURL}/uploadFile2',
                        // [默认值:'file']  设置文件上传域的name。
                        fileVal:'upload',
                        // 选择文件的按钮。可选。
                        // 内部根据当前运行是创建,可能是input元素,也可能是flash.
                        pick:
                            {
                                multiple: false,
                                id: '#filePicker'
                            },
    
                        // 上传并发数。允许同时最大上传进程数[默认值:3]   即上传文件数
                        /*这个是关键  如果开启了分片上传 并不限制同时上传的数目 会导致后台接受的分片错乱  比如按正常的分片第一片应该是开头
                        但接收的可能就变成第三片从而顺序错乱 这是由于百度webuploader默认允许同时最大上传进程数为3个
                        所以会导致接受顺序错乱从而重组发生错误,故这里设置为1*/
                        threads: 1,
    
                        // 自动上传修改为手动上传
                        auto: false,
                        //是否要分片处理大文件上传。
                        chunked: true,
                        // 如果要分片,分多大一片? 默认大小为5M.
                        chunkSize: 5 * 1024 * 1024,
                        // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
                        resize: false,
                        formData: {
                            guid: Math.random() //这里主要用于命名存储小文件的临时文件夹
                                }
                    });
    
    
                    //当有文件添加进来的时候
                    uploader.on('fileQueued', function (file) {
    
                       //重新选择文件 进行清空
                       $("#fileList").html("");
    
                        //具体逻辑根据项目需求来写  这里知识简单的举个例子写下
                       $one = $("<div id='"+file.id+"'>"+file.name+"</div>");
                       $two = $("<div id='state'>等待上传......</div>");
                       $("#fileList").append($one);
                       $("#fileList").append($two);
    
                        });
    
    
                    // 文件上传过程中创建进度条实时显示。
                    uploader.on('uploadProgress', function (file, percentage) {
                        // 具体逻辑...
                        console.log("uploadProgress===="+percentage);
                        $("#state").text("正在上传中...");
    
                    });
    
                    // 文件上传成功处理。
                    uploader.on('uploadSuccess', function (file, response) {
                        // 具体逻辑...
                        console.log('upload success...
    ');
                        console.log(uploader.options.formData.guid);
                        console.log(file.name);
    
                        //合并文件
                        $.post(
                            "${baseURL}/mergeFile",
                            //发送到后台的参数
                            {
                                guid: uploader.options.formData.guid,
                                chunks: Math.ceil(file.size / (5 * 1024 * 1024)),
                                fileName: file.name
                            },
                            function(data){
    
                            });
    
                        $("#state").text("文件上传成功啦~~~");
                    });
    
    
                    // 文件上传失败处理。
                    uploader.on('uploadError', function (file) {
                        // 具体逻辑...
                    });
                    // 上传传完毕,不管成功失败都会调用该事件,主要用于关闭进度条
                    uploader.on('uploadComplete', function (file) {
                        // 具体逻辑...
                    });
    
    
    
                    //点击上传按钮触发事件
                    $("#btnClick").click(function(){
                        uploader.upload();
                    });
    
    
    
                    //取消上传
                    $("#btnCancel").click(function(){
                        //逻辑处理..
                    });
    
                });
        </script>
    
    </head>
    <body style="padding:10px">
    <div id="layout1">
        <div id="uploader-demo">
            <div id="fileList" ></div>
            <div id="filePicker" >选择文件</div>
            <button id="btnClick">开始上传</button>
            <button id="btnCancel">取消上传</button>
        </div>
    </div>
    </body>
    </html>

      后台action:

    /**
     * Description:com.ims.action
     * Author: Eleven
     * Date: 2017/12/26 10:50
     */
    @Controller("FileAction")
    public class FileAction {
    
        /*用于接收分割请求的每个小文件的相关参数*/
        //记得提供对应的get set方法
        //上传文件对象(和表单type=file的name值一致)
        private File upload;
        //文件名
        private String uploadFileName;
        //上传类型
        private String uploadContentType;
    
        /**
         * 以下变量都是public,参数太多,不想设为private再去写get,set方法了,
         * 就偷个懒直接用了public了
         */
        //文件分片序号
        public String chunk;
    
        public String guid;//合并与分割都有用到
    
        //用于接收发送合并请求的相关参数
        public String fileName; //文件名
        public String chunks;  //分割数量
    
    
      //当进行分片上传文件的时候,每上传一个小文件就会调用这个方法,这个就跟普通的保存文件没啥区别的
        public void uploadFile2() throws Exception{
            String str = "D:/upload44/divide/";  //文件保存路径
            //保存每个小文件的路径
            String realPath = str + guid +"/" + chunk;
            File tmp =new File(realPath);
            FileUtils.copyFile(upload, tmp);
            System.out.println("上传文件"+uploadFileName+",第几块:"+chunk+",大小:"+(upload.length()/1024/1024)+"M");
    
        }
    
    
      //文件合并
        public void mergeFile() throws Exception{
    
            String path = "D:/upload44/merge/" ;
            //创建 合并文件夹
            new File(path).mkdir();
    
            //创建 合并后的文件
            File newFile = new File(path + fileName);
            if(!newFile.exists()){
                newFile.createNewFile();
            }
    
            FileOutputStream outputStream = new FileOutputStream(newFile, true);//文件追加写入
    
            byte[] byt = new byte[10 * 1024 * 1024];
            int len;
            FileInputStream temp = null;//分片文件
            for (int i = 0; i < Integer.parseInt(chunks); i++) {
                //"D:/upload44/divide/" + guid + "/" + i 为保存分割后的小文件的路径
                temp = new FileInputStream(new File("D:/upload44/divide/" + guid + "/" + i));
                while ((len = temp.read(byt)) != -1) {
                    System.out.println(len);
                    outputStream.write(byt, 0, len);
    
                }
                temp.close();
            }
    
             //当所有追加写入都写完  才可以关闭流
            outputStream.close();
    
            //删除分片文件
            String path2 = "D:/upload44/divide/" + guid;
            FileUtils.deleteDirectory(new File(path2));//删除目录下所有的内容
    
            System.out.println("success!guid=" + guid + ";chunks=" + chunks + ";fileName=" + fileName);
    
        }
        
        
    
        public File getUpload() {
            return upload;
        }
    
        public void setUpload(File upload) {
            this.upload = upload;
        }
    
        public String getUploadFileName() {
            return uploadFileName;
        }
    
        public void setUploadFileName(String uploadFileName) {
            this.uploadFileName = uploadFileName;
        }
    
        public String getUploadContentType() {
            return uploadContentType;
        }
    
        public void setUploadContentType(String uploadContentType) {
            this.uploadContentType = uploadContentType;
        }
    }

      struts.xml配置:

    <action name="uploadFile2" class="FileAction" method="uploadFile2">
    </action>
    <action name="mergeFile" class="FileAction" method="mergeFile">
    </action>

      

      好啦,到这里,一个简单的文件分片断点上传就完成了~~~~~~~~又有新任务来了,干活干活!!!

      对了补充说明下,后台只是接收了一些简单的参数而已,而从前台WebUploader传递过来的参数当然不止上面那几个了,所以,可以学会用F12调试模式,进行查看发送的请求,以及相关的请求参数,这里就不多说了

      运行截图:

      

      

  • 相关阅读:
    MySQL中的char与varchar详解
    有关PHPstorm的git环境的配置和git密钥的生成总结
    PHP开发中常用的字符串操作函数
    PHP 二维数组排序函数的应用 array_multisort()
    大龄程序员的出路在哪里
    近期面试总结(PHP后端开发工程师)(部分笔试题)
    B-Tree目录和Hash索引的区别
    curl、fopen和file_get_contents区别
    什么是OAuth授权
    SEO 统计算法
  • 原文地址:https://www.cnblogs.com/eleven258/p/8135993.html
Copyright © 2011-2022 走看看