圖片/文件上傳 - layui.upload

                    上傳模塊自 layui 2.0 的版本開始,進行了全面重寫,這使得它不再那么單一,它所包含的不僅是更為強勁的功能,還有靈活的UI。任何元素都可以作為上傳組件來調用,譬如按鈕、圖片、普通的DIV等等,而不再是一個單調的file文件域。

                    模塊加載名稱:upload

                    快速使用

                    一切從小試牛刀開始。通常情況下,我們上傳文件是借助 type="file" 的 input 標簽來完成的,但非常遺憾的是,它不能很好地與其它表單元素并存,所以我們常常要單獨為它做一個業務層面的“異步上傳”,即先讓圖片上傳,再和其它表單一起提交保存。下面是一個小示例:

                    這原本只是一個普通的 button,正是 upload 模塊賦予了它“文件選擇”的特殊技能。當然,你還可以隨意定制它的樣式,而不是只局限于按鈕。

                    <!DOCTYPE html>
                    <html>
                    <head>
                      <meta charset="utf-8">
                      <title>upload模塊快速使用</title>
                      <link rel="stylesheet" href="/static/build/layui.css" media="all">
                    </head>
                    <body>
                     
                    <button type="button" class="layui-btn" id="test1">
                      <i class="layui-icon">&#xe67c;</i>上傳圖片
                    </button>
                     
                    <script src="/static/build/layui.js"></script>
                    <script>
                    layui.use('upload', function(){
                      var upload = layui.upload;
                       
                      //執行實例
                      var uploadInst = upload.render({
                        elem: '#test1' //綁定元素
                        ,url: '/upload/' //上傳接口
                        ,done: function(res){
                          //上傳完畢回調
                        }
                        ,error: function(){
                          //請求異常回調
                        }
                      });
                    });
                    </script>
                    </body>
                    </html>

                    一切看起來是那樣的簡單,乃至于我不得不湊一段文字來填充這一行的版面。這樣好像與下文銜接起來會比較諧調的樣子(自我感覺)

                    核心方法與基礎參數選項

                    使用 upload 模塊必須與 upload.render(options) 方法打交道,其中的 options即為基礎參數,它是一個對象。

                    var upload = layui.upload; //得到 upload 對象
                     
                    //創建一個上傳組件
                    upload.render({
                      elem: '#id'
                      ,url: ''
                      ,done: function(res, index, upload){ //上傳后的回調
                      
                      } 
                      //,accept: 'file' //允許上傳的文件類型
                      //,size: 50 //最大允許上傳的文件大小
                      //,……
                    })
                          

                    從 layui 2.1.0 開始,允許你直接在元素上設定基礎參數,如:

                    【HTML】
                    <button class="layui-btn test" lay-data="{url: '/a/'}">上傳圖片</button>
                    <button class="layui-btn test" lay-data="{url: '/b/', accept: 'file'}">上傳文件</button>
                     
                    【JS】
                    upload.render({
                      elem: '.test'
                      ,done: function(res, index, upload){
                        //獲取當前觸發上傳的元素,一般用于 elem 綁定 class 的情況,注意:此乃 layui 2.1.0 新增
                        var item = this.item;
                      }
                    })
                          

                    更多支持的參數詳見下表,合理的配置它們,應對各式各樣的業務需求。

                    參數選項 說明 類型 默認值
                    elem 指向容器選擇器,如:elem: '#id'。也可以是DOM對象 string/object -
                    url 服務端上傳接口,返回的數據規范請詳見下文 string -
                    data 請求上傳接口的額外參數。如:data: {id: 'xxx'}
                    從 layui 2.2.6 開始,支持動態值,如:
                    data: {
                      id: function(){
                        return $('#id').val();
                      }
                    }
                                
                    object -
                    headers 接口的請求頭。如:headers: {token: 'sasasas'}。注:該參數為 layui 2.2.6 開始新增
                    accept 指定允許上傳時校驗的文件類型,可選值有:images(圖片)、file(所有文件)、video(視頻)、audio(音頻) string images
                    acceptMime 規定打開文件選擇框時,篩選出的文件類型,值為用逗號隔開的 MIME 類型列表。如:
                    acceptMime: 'image/*'(只顯示圖片文件)
                    acceptMime: 'image/jpg, image/png'(只顯示 jpg 和 png 文件)
                    注:該參數為 layui 2.2.6 開始新增
                    string images
                    exts 允許上傳的文件后綴。一般結合 accept 參數類設定。假設 accept 為 file 類型時,那么你設置 exts: 'zip|rar|7z' 即代表只允許上傳壓縮格式的文件。如果 accept 未設定,那么限制的就是圖片的文件格式 string jpg|png|gif|bmp|jpeg
                    auto 是否選完文件后自動上傳。如果設定 false,那么需要設置 bindAction 參數來指向一個其它按鈕提交上傳 boolean true
                    bindAction 指向一個按鈕觸發上傳,一般配合 auto: false 來使用。值為選擇器或DOM對象,如:bindAction: '#btn' string/object -
                    field 設定文件域的字段名 string file
                    size 設置文件最大可允許上傳的大小,單位 KB。不支持ie8/9 number 0(即不限制)
                    multiple 是否允許多文件上傳。設置 true即可開啟。不支持ie8/9 boolean false
                    number 設置同時可上傳的文件數量,一般配合 multiple 參數出現。
                    注意:該參數為 layui 2.2.3 開始新增
                    number 0(即不限制)
                    drag 是否接受拖拽的文件上傳,設置 false 可禁用。不支持ie8/9 boolean true
                    回調
                    choose 選擇文件后的回調函數。返回一個object參數,詳見下文 function -
                    before 文件提交上傳前的回調。返回一個object參數(同上),詳見下文 function -
                    done 執行上傳請求后的回調。返回三個參數,分別為:res(服務端響應信息)、index(當前文件的索引)、upload(重新上傳的方法,一般在文件上傳失敗后使用)。詳見下文 function -
                    error 執行上傳請求出現異常的回調(一般為網絡異常、URL 404等)。返回兩個參數,分別為:index(當前文件的索引)、upload(重新上傳的方法)。詳見下文 function -
                    上傳接口

                    設定一個 URL 地址給 url 參數,用來告訴 upload 模塊的服務端上傳接口。像你平時使用Ajax一樣。如:

                    upload.render({
                      elem: '#id'
                      ,url: '/api/upload/' //必填項
                      ,method: ''  //可選項。HTTP類型,默認post
                      ,data: {} //可選項。額外的參數,如:{id: 123, abc: 'xxx'}
                    });      
                          

                    該接口返回的相應信息(response)必須是一個標準的 JSON 格式,如:

                    {
                      "code": 0
                      ,"msg": ""
                      ,"data": {
                        "src": "http://cdn.layui.com/123.jpg"
                      }
                    }       
                          

                    注意1:你不一定非得按照上述格式返回,只要是合法的 JSON 字符即可。其響應信息會轉化成JS對象傳遞給 done 回調。
                    注意2:如果上傳后,出現文件下載框(一般為ie下),那么你需要在服務端對response的header設置 Content-Type: text/html

                    選擇文件的回調

                    在文件被選擇后觸發,該回調會在 before 回調之前。一般用于非自動上傳(即 auto: false )的場景,比如預覽圖片等。

                    upload.render({
                      elem: '#id'
                      ,url: '/api/upload/'
                      ,auto: false //選擇文件后不自動上傳
                      ,bindAction: '#testListAction' //指向一個按鈕觸發上傳
                      ,choose: function(obj){
                        //將每次選擇的文件追加到文件隊列
                        var files = obj.pushFile();
                        
                        //預讀本地文件,如果是多文件,則會遍歷。(不支持ie8/9)
                        obj.preview(function(index, file, result){
                          console.log(index); //得到文件索引
                          console.log(file); //得到文件對象
                          console.log(result); //得到文件base64編碼,比如圖片
                          
                          //obj.resetFile(index, file, '123.jpg'); //重命名文件名,layui 2.3.0 開始新增
                          
                          //這里還可以做一些 append 文件列表 DOM 的操作
                          
                          //obj.upload(index, file); //對上傳失敗的單個文件重新上傳,一般在某個事件中使用
                          //delete files[index]; //刪除列表中對應的文件,一般在某個事件中使用
                        });
                      }
                    });      
                          

                    事實上這是一個非常實用的存在,可輕松應對復雜的列表文件上傳管理。具體可移步到 示例 頁面,里面有一個文件列表的小例子。

                    文件上傳前的回調

                    choose 回調之后、done/error 回調之前觸發。返回的參數完全類似 choose 回調。一般用于上傳完畢前的loading、圖片預覽等。

                    upload.render({
                      elem: '#id'
                      ,url: '/api/upload/'
                      ,before: function(obj){ //obj參數包含的信息,跟 choose回調完全一致,可參見上文。
                        layer.load(); //上傳loading
                      }
                      ,done: function(res, index, upload){
                        layer.closeAll('loading'); //關閉loading
                      }
                      ,error: function(index, upload){
                        layer.closeAll('loading'); //關閉loading
                      }
                    });      
                          
                    上傳接口請求成功的回調

                    在上傳接口請求完畢后觸發,但文件不一定是上傳成功的,只是接口的響應狀態正常(200)。回調返回三個參數,分別為:服務端響應信息當前文件的索引重新上傳的方法

                    upload.render({
                      elem: '#id'
                      ,url: '/api/upload/'
                      ,done: function(res, index, upload){
                        //假設code=0代表上傳成功
                        if(res.code == 0){
                          //do something (比如將res返回的圖片鏈接保存到表單的隱藏域)
                        }
                        
                        //獲取當前觸發上傳的元素,一般用于 elem 綁定 class 的情況,注意:此乃 layui 2.1.0 新增
                        var item = this.item;
                        
                        //文件保存失敗
                        //do something
                      }
                    });      
                          
                    上傳請求失敗的回調

                    當請求上傳時出現異常時觸發(如網絡異常、404/500等)。回調返回兩個參數,分別為:當前文件的索引重新上傳的方法

                    upload.render({
                      elem: '#id'
                      ,url: '/api/upload/'
                      ,error: function(index, upload){
                        //當上傳失敗時,你可以生成一個“重新上傳”的按鈕,點擊該按鈕時,執行 upload() 方法即可實現重新上傳
                      }
                    });      
                          
                    多文件上傳完畢后的狀態回調

                    只有當開啟多文件時(即 multiple: true),該回調才會被觸發。回調返回一個 object 類型的參數,包含一些狀態數據:

                    upload.render({
                      elem: '#id'
                      ,url: '/api/upload/'
                      ,multiple: true
                      ,allDone: function(obj){ //當文件全部被提交后,才觸發
                        console.log(obj.total); //得到總文件數
                        console.log(obj.successful); //請求成功的文件數
                        console.log(obj.aborted); //請求失敗的文件數
                      }
                      ,done: function(res, index, upload){ //每個文件提交一次觸發一次。詳見“請求成功的回調”
                      
                      }
                    });      
                          
                    文件上傳進度的回調

                    在網速一般的情況下,大文件的上傳通常需要一定時間的等待,而瀏覽器并不會醒目地告知你它正在努力地上傳中,此時為了提升用戶體驗,我們可以通過該回調制作一個進度條。注:該回調為 layui 2.5.5 新增

                    upload.render({
                      elem: '#id'
                      ,url: '/api/upload/'
                      ,progress: function(n){
                        var percent = n + '%' //獲取進度百分比
                        element.progress('demo', percent); //可配合 layui 進度條元素使用
                      }
                    });       
                          
                    重載實例

                    有時你可能需要對 upload.render() 實例進行重載,通過改變一些參數(如將上傳文件重置為只上傳圖片等場景)來重置功能。如:

                    //創建一個實例
                    var uploadInst = upload.render({
                      elem: '#id'
                      ,url: '/api/upload/'
                      ,size: 1024*5 //限定大小
                    });
                     
                    //重載該實例,支持重載全部基礎參數
                    uploadInst.reload({
                      accept: 'images' //只允許上傳圖片
                      ,acceptMime: 'image/*' //只篩選圖片
                      ,size: 1024*2 //限定大小
                    }); 
                          

                    注意:該方法為 layui 2.5.0 開始新增

                    重新上傳

                    在執行 upload.render(options) 方法時,其實有返回一個實例對象,以便對完成重新上傳等操作。注意:這是對當前上傳隊列的全局重新上傳,而 choose 回調返回的 obj.upload(index, file) 方法則是對單個文件進行重新上傳。如:

                    var uploadInst = upload.render({
                      elem: '#id'
                      ,url: '/api/upload/'
                      ,choose: function(obj){
                        obj.preview(function(index, file, result){
                          //對上傳失敗的單個文件重新上傳,一般在某個事件中使用
                          //obj.upload(index, file);
                        });
                      }
                    });
                     
                    //重新上傳的方法,一般在某個事件中使用
                    //uploadInst.upload(); 
                          
                    跨域上傳

                    有些時候,可能會涉及到文件跨域操作,過去版本的 upload 模塊最大的缺陷恰恰在于這里。而從 layui 2.0 的版本開始,我們已經對 跨域做了支持。但鑒于代碼的冗余度等多方面考慮,在IE9以下版本環境中,仍然不支持跨域。其它所有版本的IE和Chrome/FireFox等高級瀏覽器均支持。

                    那么,需要你怎么做?通常來說,是借助 CORS(跨資源共享) 方案,即對接口所在的服務器設置:Access-Control-Allow-Origin 詳見Google,配置起來還是挺簡單的。而至于域名限制,一般是服務端程序中去做處理。這里不做過多贅述。

                    亚洲图色