1. 程式人生 > >WEUI檔案上傳詳解

WEUI檔案上傳詳解

本文通過我個人設計的系統為案例來教會讀者使用weui的uploader,先來看看效果圖:

                                                                                                圖片上傳框

                                                                                                   PC端

                                                                                                移動端

首先,微信的官方文件不會一步一步教會你怎麼用,但是在其中能發現很多使用的細節,推薦看一下,遇到問題可以找到解決方法:

下面,通過我係統的案例讓大家一步步瞭解如何使用weui的uploader:

1、編寫檔案上傳框Html

<div class="weui-cells__title">商品圖片上傳</div>
<div class="weui-cells weui-cells_form" id="uploader">
    <div class="weui-cell">
        <div class="weui-cell__bd">
            <div class="weui-uploader">
                <div class="weui-uploader__hd">
                    <p class="weui-uploader__title">圖片列表</p>
                    <div class="weui-uploader__info">
                        <span id="uploadCount">0</span>/4
                    </div>
                </div>
                <div class="weui-uploader__bd">
                    <ul class="weui-uploader__files" id="uploaderFiles"></ul>
                    <div class="weui-uploader__input-box">
                        <input id="uploaderInput" class="weui-uploader__input" type="file"
                               accept="image/*" multiple="">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

把div塊放到你想要的位置,著重關注帶id的標籤,之後的上傳相關的js程式碼中都會有使用到!!!

2、編寫圖片上傳的js程式碼

/* *
 * 圖片上傳
 * */
var uploadCount = 0,  //上傳圖片的數量
    uploadList = [],  //上傳的圖片
    uploadSuccessCount = 0;  //上傳成功的數量
var uploadCountDom = document.getElementById("uploadCount");
weui.uploader('#uploader', {
    url: 'img-api/upload_imgs',  //你要上傳的url地址
    auto: true,
    type: 'file',
    fileVal: 'fileVal',  //檔案上傳域的name,後臺通過該name拿到傳輸的檔案
    compress: {
        width: 1600,
        height: 1600,
        quality: .8
    },
    onBeforeQueued: function onBeforeQueued(files) {
        //上傳前,對上傳的情況做以下多個判斷,保證合法性,可自行刪改
        if (["image/jpg", "image/jpeg", "image/png", "image/gif"].indexOf(this.type) < 0) {
            weui.alert('請上傳圖片');
            return false;
        }
        if (this.size > 5 * 1024 * 1024) {
            weui.alert('請上傳不超過5M的圖片');
            return false;
        }
        if (files.length > 4) {
            //防止一下子選中過多檔案
            weui.alert('最多隻能上傳4張圖片,請重新選擇');
            return false;
        }
        if (uploadCount + 1 > 4) {
            weui.alert('最多隻能上傳4張圖片');
            return false;
        }
        if (localStorage.userId == undefined) {
            weui.alert('請先登入!');
            return false;
        }

        ++uploadCount;
        uploadCountDom.innerHTML = uploadCount;
    },
    onQueued: function onQueued() {
        uploadList.push(this);
        //手動上傳,如果不想選擇完圖片自動上傳可以通過此方法改為手動不過上面的auto要改為false
        /*var self = this;
        $('#preview_confirm').on('click',function(){
            self.upload();
        });*/
    },
    onBeforeSend: function onBeforeSend(data, headers) {
        $("#submit_order").addClass("weui-btn_disabled");
        //return false; //阻止檔案上傳
    },
    onProgress: function onProgress(procent) {
        //console.log(this, procent);
    },
    onSuccess: function onSuccess(ret) {
        if (ret.result == true) {
            uploadSuccessCount++;
            if (uploadSuccessCount == uploadCount) {
                //判斷上傳是否全部成功
                $("#submit_order").removeClass("weui-btn_disabled");
            }
        }
        var uploadID = this.id;
        $("#uploaderFiles li").each(function () {
            if ($(this).attr("data-id") == uploadID) {
                $(this).attr("DB-id", ret.DBId);  //圖片後臺對應的唯一編號
                $(this).attr("url", ret.url);  //圖片存放地址
            }
        });
        //console.log(this, ret);
    },
    onError: function onError(err) {
        console.log(this, err);
    }
});

關鍵的地方我都通過註釋標註了出來,上面的重點就是在從id為uploaderFiles的ul標籤中找到新加入的li標籤,這裡面存放著上傳的圖片資訊,給其加上編號和地址兩個屬性方便後續預覽或刪除

3、編寫縮圖預覽js程式碼

/* *
 * 縮圖預覽
 * */
document.querySelector('#uploaderFiles').addEventListener('click', function (e) {
    var target = e.target;

    while (!target.classList.contains('weui-uploader__file') && target) {
        target = target.parentNode;
    }
    if (!target) return;

    //從圖片對應的li標籤中獲得所需屬性
    var url = target.getAttribute('url');  //圖片存放地址
    var DBId = target.getAttribute('db-id');  //圖片唯一編號
    var id = target.getAttribute('data-id');  //點選圖片對應的id

    var gallery = weui.gallery(url, {
        className: 'custom-name',
        onDelete: function () {
            //刪除圖片的回撥
            var isDelete = confirm('確定刪除該圖片?');
            if (isDelete) {
                --uploadCount;
                uploadCountDom.innerHTML = uploadCount;  //處理角標
                for (var i = 0, len = uploadList.length; i < len; ++i) {
                    var file = uploadList[i];
                    if (file.id == id) {
                        $("#uploaderFiles li").each(function () {
                            //找到對應的li標籤,請求後臺刪除檔案
                            if ($(this).attr("data-id") == id) {
                                var param = {};
                                param.DBId = DBId;
                                param.imgUrl = url;
                                $.ajax({
                                    url: "img-api/delete_imgs",
                                    type: "delete",
                                    contentType: "application/json;charset=UTF-8",
                                    dataType: "json",
                                    data: JSON.stringify(param),
                                    success: function (msg) {
                                        console.log(msg);
                                    },
                                    error: function (xhr, textstatus, thrown) {

                                    }
                                });
                            }
                        });
                        file.stop();
                        break;
                    }
                }
                target.remove();
                gallery.hide();
            }
        }
    });
});

這部分程式碼比較統一,需要修改的可能就是請求後臺刪除圖片部分

4、引用的第三方檔案

<!--微信ui-->
<link rel="stylesheet" href="../static/lib/css/weui.min.css"/>
<link rel="stylesheet" href="../static/lib/css/jquery-weui.min.css"/>
<!--第三方庫-->
<script type="text/javascript" src="../static/lib/weui.min.js"></script>
<script type="text/javascript" src="../static/lib/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="../static/lib/jquery-weui.min.js"></script>

5、後臺圖片檔案操作

我使用flask編寫的專案,但是大致思路是一樣的,放出來大家參考一下:

class uploadImgs(Resource):
    def post(self):
        if request.method == 'POST':
            # 獲得post過來的圖片
            file = request.files['fileVal']
            # 判斷是否是圖片
            if file and file.filename.rsplit('.', 1)[1] in config.ALLOWED_EXTENSIONS:
                # 將名字命名為唯一的
                DBId = self.create_uid()
                filename = secure_filename(file.filename)
                filename = DBId + "." + filename.split(".")[1]
                # 將檔案儲存到指定位置
                base_path = path.abspath(path.dirname(__file__))
                upload_path = path.join(base_path, config.UPLOAD_FOLDER)
                file.save(upload_path + filename)
                # 定時4個小時後清除沒有下單但上傳的圖片
                Timer(14400, self.operateImgs, (base_path, upload_path, filename)).start()

                res_data = {'result': True, 'url': config.UPLOAD_FOLDER + filename,
                            'DBId': DBId}
                return res_data

    def create_uid(self):
        return str(uuid.uuid1())
    
    # 這部分僅僅是一個初步的思路,還沒進行優化,不建議參考
    def operateImgs(self, basePath, uploadPath, fileName):
        # 刪除上傳的檔案
        os.remove(uploadPath + fileName)
        # 如果成功下單了,去臨時資料夾拷貝圖片回來,並刪除臨時圖片
        if (os.path.exists(path.join(basePath, TEMP_UPLOAD_FOLDER + fileName))):
            shutil.copyfile(path.join(basePath, TEMP_UPLOAD_FOLDER + fileName), uploadPath + fileName)
            os.remove(path.join(basePath, TEMP_UPLOAD_FOLDER + fileName))
            return


class getImgs(Resource):
    def get(self, filename):
        base_path = path.abspath(path.dirname(__file__))
        upload_path = path.join(base_path, config.UPLOAD_FOLDER)
        return send_from_directory(upload_path,
                                   filename)


class deleteImgs(Resource):
    def delete(self):
        data = request.get_json()
        base_path = path.abspath(path.dirname(__file__))
        upload_file = path.join(base_path, data['imgUrl'])
        if os.path.exists(upload_file):
            os.remove(upload_file)
            return True
        else:
            return False

上傳圖片的方法中,通過唯一的編號給圖片檔案命名,存放在指定的目錄中,這樣子無論是在刪除還是預覽中都比較方便。但是這裡有個問題,由於是自動上傳,圖片會一直自動累積在後臺中,包括一些無效的圖片,所以採用定時的方法檢測無效的圖片並刪除(無效是相對的,具體看你專案裡怎麼定義,我的專案裡就是沒下單的但上傳的圖片),方法比較粗暴,望各位指導。

圖片預覽和刪除就比較簡單了,不在贅述。

至此weui的uploader講解完畢。

若有錯誤煩請指出,有地方不理解歡迎討論。