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...\n');
                    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調試模式,進行查看發送的請求,以及相關的請求參數,這里就不多說了

  運行截圖:

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM