移動端使用localResizeIMG4壓縮圖片並上傳

泥猴桃發表於2018-12-20

現在的移動端前端開發上傳圖片的功能太常見了,一般的情況下我們都是用input 標籤來搞,或者是在網上找一些現成的圖片上傳外掛來做。但是有的外掛程式碼量確實比較多。依賴也比較多。
而且移動端圖片上傳和pc 端圖片上傳還是有點差別的,如果涉及到幾M大的圖片在pc端上感測覺沒什麼,但是在移動端的話,因為圖片質量太大,很容易上傳失敗。實在是噁心。這時候我們就要用到 localResizeIMG4 這個圖片壓縮外掛。直接把圖片轉成base64格式的字串。質量也會小很多,移動端上傳速度也會很快。

完整demo 以上傳到github: https://github.com/dadanihoutao/img-upload.git

簡單介紹一下 localResizeIMG4 :

相容IOS,Android,PC、自動按需載入檔案
支援壓縮比例
支援原生JS、jQuery/Zepto
支援Promise特性
使用Base64

下載地址

localResizeIMG共有4個歷史版本,每個版本間使用方法可能不一樣。我們以最新穩定版本localResizeIMG4為例。

https://github.com/think2011/localResizeIMG/archive/4.9.35.zip

使用方法

html頁面直接引入
解壓以後js檔案目錄是這樣
在這裡插入圖片描述

所有js檔案都複製到專案裡,不要嫌多, 至於為什麼 箭頭指向的.txt 檔案裡說明如下:

1. 一般情況僅需引用 【lrz.bundle.js】 即可。 但絕對不要刪除目錄下的【.chunk.js】,這些檔案分別對應了IOS和Android的相容程式碼,檢測到符合環境時會自動引入。 2. 【lrz.all.bundle.js】是包含了所有引用了,莫名其妙的問題下就引用這個吧。 例如:https://github.com/think2011/localResizeIMG/issues/6 3. 【.map】檔案是供除錯用的,正式使用刪不刪除都沒關係,因為僅在除錯時才會載入。也能解決微信端,qq瀏覽器,上傳圖片無法觸發 input type=“file” 問題

<script src="./dist/lrz.bundle.js"></script>
<input id="uploadfile" name="image" type="file"  capture="camera" accept="image/*" multiple  value="選擇圖片">

multiple 這個屬性加上,支援上傳多張圖片或者多個檔案
capture=“camera” 這個屬性加上,點選input 按鈕的時候可以直接呼叫到相機;
accept=“image/*” 這個屬性加上 可以呼叫到相機和檔案,如下圖

在這裡插入圖片描述
accept=“image/*” 不加的話 如下圖:
在這裡插入圖片描述
用小米手機的 自帶瀏覽器和google 瀏覽器測試效果

通過change事件可以得到使用者選擇的圖片

也可以使用原生js 來實現圖片上傳

document.querySelector('input').addEventListener('change', function () {
    // this.files[0] 是使用者選擇的檔案
    lrz(this.files[0], {width: 1024})
        .then(function (rst) {
        
            // 把處理的好的圖片給使用者看看唄(可選)
            var img = new Image();
            img.src = rst.base64; //base64字串

            img.onload = function () {
                document.body.appendChild(img);
            };

            return rst;
        })

        .then(function (rst) {
            // 這裡該上傳給後端啦

            /* ==================================================== */
            // 原生ajax上傳程式碼,所以看起來特別多,但絕對能用
            // 其他框架,例如jQuery處理formData略有不同,請自行google,baidu。
            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'http://localhost:5000/');

            xhr.onload = function () {
                if (xhr.status === 200) {
                    // 上傳成功
                } else {
                    // 處理其他情況
                }
            };

            xhr.onerror = function () {
                // 處理錯誤
            };

            xhr.upload.onprogress = function (e) {
                // 上傳進度
                var percentComplete = ((e.loaded / e.total) || 0) * 100;
            };

            // 新增引數
            rst.formData.append('fileLen', rst.fileLen);
            rst.formData.append('xxx', '我是其他引數');

            // 觸發上傳
            xhr.send(rst.formData);
            /* ==================================================== */

            return rst;
        })

        .catch(function (err) {
            // 萬一出錯了,這裡可以捕捉到錯誤資訊
            // 而且以上的then都不會執行

            alert(err);
        })

        .always(function () {
            // 不管是成功失敗,這裡都會執行
        });
});

下邊是一個jq 移動端 完整的例子包括css js html

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>上傳圖片</title>
<!-- 這裡自行引入 -->
    <script src="src/js/jquery.min.js"></script>
    <script src="src/js/lrz.bundle.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .container-fluid {
            width: 100%;
        }
        .image {
            width: 100%;
            font-size: 20px;
            text-align: center;
        }
        .imagebox {
            width: 80%;
            height: 200px;
            margin: 0 auto;
            border: 1px solid #cccccc;
            text-align: center;
        }
        .image {
            height: 200px;
            max-width: 80%;
            max-height: 200px;
        }
        .uploadWrap {
            width: 100px;
            height: 40px;
            position: relative;
            margin-top: 20px;
            overflow: hidden;
            background-color: #cccccc;
            left: 50%;
            transform: translateX(-50%);
        }
        .uploadWrap span {
            font-size: 20px;
            color: #333333;
            line-height: 40px;
        }
        #uploadfile {
            position: absolute;
            width: 100px;
            height: 40px;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            opacity: 0;
        }
        .submit {
            width: 80%;
            height: 40px;
            background-color: #cccccc;
            border: none;
            outline: none;
            position: relative;
            left: 50%;
            transform: translateX(-50%);
            margin-top: 20px;
        }

    </style>
</head>

<body>
    <div class="container-fluid">
        <form>
            <div class="form-group">
                <label>圖片上傳</label>
                <div class="imagebox">
                </div>
                <div class="uploadWrap">
                    <span>請選擇圖片</span>
                    <input id="uploadfile" name="image" type="file"  capture="camera" accept="image/*" value="選擇圖片">
                </div>
            </div>
            <button class="submit">提交</button>
        </form>
    </div>

    <script>
        $(function () {
            var imgbase64 = '';
            // 圖片壓縮預覽
            $('#uploadfile').on('change', function () {
                console.log(this.files[0])
                lrz(this.files[0], { width: 500  })
                    .then(function (rst) {
                        // 處理成功會執行
                        console.log(rst);
                        imgbase64 = rst.base64;
                        var img = new Image();
                        img.src = imgbase64;
                        if(!!$('.imagebox').find('img')){
                            $('.imagebox').find('img').remove('img');
                        }
                        $('.imagebox').append($(img))
                        $('img').addClass('image')
                    })
                    .catch(function (err) {
                        // 處理失敗會執行
                    })
                    .always(function () {
                        // 不管是成功失敗,都會執行
                    });
            })

            // 提交按鈕點選事件
            $('.submit').on('click', function () {

                var formData = new FormData();
                formData.append('image', imgbase64);
                // 如果還有其他引數,可以依次append 到 formdata 物件裡,
                // formData.append('username', username);
                // formData.append('age',age)
                // console.log(formData)  //  這裡列印的話會發現formData 物件為空,但是不要在意,這些資料確實都在formData 物件裡
                $.ajax({
                    type: 'POST',
                    url: '/apis/customer/add',
                    data: formData,
                    async: false,
                    processData: false,
                    contentType: false,
                    dataType: 'json',
                    success: function (data) {
                        console.log(data)
                    },
                    error: function (error) {
                        console.log(error)
                    }
                })
            })
        })
    </script>
</body>

</html>

jq 的效果圖是這樣的 樣式寫的有點爛講究這看哈:
在這裡插入圖片描述
我們都知道,如果直接用input type=“file” 的話,會出現一個 未選中任何檔案 的文字提示
在這裡插入圖片描述

噁心巴拉,即使上傳圖片成功這裡也會變成圖片的名字。
上邊的jq demo中用css 做了一下處理 直接把這個input opacity:0隱藏掉了!

返回的rst物件資料示例:

在這裡插入圖片描述
其中base64屬性是帶圖片型別的base64編碼,可直接用於img標籤的src。

引數

lrz(file, [options]);

file 通過 input:file 得到的檔案,或者直接傳入圖片路徑

[options] 這個引數允許忽略
width {Number} 圖片最大不超過的寬度,預設為原圖寬度,高度不設時會適應寬度。
height {Number} 同上
quality {Number} 圖片壓縮質量,取值 0 - 1,預設為0.7
fieldName {String} 後端接收的欄位名,預設:file

壓縮完成返回的結果

返回值是一個promise物件

then(rst)
rst.formData 後端可處理的資料
rst.file 壓縮後的file物件(預設已經丟在rst.formData有一份了),需要注意的是如果壓縮率太低的話,這個會是原始的file物件
rst.fileLen 生成後的圖片的大小,後端可以通過此值來校驗是否傳輸完整
rst.base64 生成後的圖片base64,後端可以處理此字串為圖片,也直接用於img.src = base64
rst.base64Len 生成後的base64的大小,後端可以通過此值來校驗是否傳輸完整 (如果採用base64上傳方式)
rst.origin 也就是原始的file物件,裡面存了一些原始檔案的資訊,例如大小,日期等。
catch(err)

always()

lrz原理

基本原理是通過canvas渲染圖片,再通過 toDataURL 方法壓縮儲存為base64字串(能夠編譯為jpg格式的圖片)。

詳見WIKI

相關文章