1. 程式人生 > >七牛雲上傳--官方JSDK與photoClip截圖Base64編碼

七牛雲上傳--官方JSDK與photoClip截圖Base64編碼

主要
1、php後臺生成七牛雲uploadtoken
2、前端使用官方JSDK上傳原圖
3、photoClip截圖 生成Base64圖片
4、上傳base64 編碼圖片到七牛雲

php後臺生成uploadtoken

下載php的SDK,然後引用SDK中的Auth即可:
七牛雲官方php的SDK

use Think\Controller;
use Qiniu\Auth;
use Qiniu\Storage\UploadManager;
use Org\Net\Http;
class QiniuLogic extends Controller{
    public function
get_token(){
$accessKey = C("QINIU_ACCESS"); //這個是七牛雲賬號的access $secretKey = C("QINIU_SECRET"); //這個是七牛雲賬號的secret $bucket = C("QINIU_BUCKET"); //這個是七牛雲的內容空間 vendor("Qiniu/autoload"); $auth = new Auth($accessKey, $secretKey); $policy = array( "scope"
=>$bucket.":".$accessKey, "insertOnly"=>0 ); $uptoken = $auth->uploadToken($bucket, null, 36000, $policy); $this->assign("QiniuToken",$uptoken); //我們要的token,必需 $this->assign("QiniuDomain",C("QINIU_DOMAIN")); //這個是cname後的域名,非必須 } }

前端頁面使用官方JSDK上傳原圖

首先,下載一個官方的JSDK
然後在html頁面中引用js,官方文件中引用的比較多,這裡引用兩個:plupload.full.min.js和qiniu.min.js就夠用了。
上傳過程中可能出現地域的問題:
常見問題處理

html頁面

    <div>
        <img id="image" src='{$gradeImg}' />
        <input type="hidden" id="qiniu-uptoken" value="{$QiniuToken}">
        <input type="hidden" id="qiniu-domain" value="{$QiniuDomain}">
        <input type="hidden" id="image_original" value="{$gradeImg}">
    </div>
    <!--七牛雲直接上傳,這裡可以參考官方的文件-->
    <div id="qiniu-upload-container" style="display: none;">
        <button id="qiniu-upload-btn" class="btn btn-success">
            上傳
        </button>
        <div id="fsUploadProgress">
        </div>
    </div>
    <!--七牛雲直接上傳end-->
    <!--七牛雲圖直接上傳,upload.js 是自己需要寫的,其它兩個是SDK檔案的-->
<script src="../qiniu/plupload/plupload.full.min.js"></script>
<script src="../qiniu/dist/qiniu.min.js"></script>
<script src="../qiniu/js/upload.js"></script>
<!--七牛雲圖直接上傳end-->

JavaScript-upload.js

官方文件中有很多內容,這裡做了一些簡化:
主要修改‘FileUploaded’,‘key’和 randStr() 方法

$(function () {
    var uploader = Qiniu.uploader({
        runtimes: 'html5,flash,html4',
        browse_button: 'qiniu-upload-btn',
        container: 'qiniu-upload-container',
        drop_element: '',
        max_file_size: '10mb',
        flash_swf_url: 'bower_components/plupload/js/Moxie.swf',
        dragdrop: false,
        chunk_size: '2mb',
        multi_selection: !(mOxie.Env.OS.toLowerCase()==="ios"),
        uptoken: $('#qiniu-uptoken').val(),
        domain: $('#qiniu-domain').val(),
        get_new_uptoken: false,
        auto_start: true,
        log_level: 5,
        init: {
            'FilesAdded': function(up, files) {
                $("#qiniu-upload-btn").html("正在上傳中...");
                $("#qiniu-upload-btn").attr("disabled",true);
            },
            'FileUploaded': function(up, file, info) { //主要是這個方法
                var res = $.parseJSON(info);
                var image = $("#qiniu-domain").val()+res.key;
                $("#image_original").val(image);
                var thumb = image+"?imageView2/2/w/500/h/300";
                $("#image").attr("src",thumb);

                $("#qiniu-upload-btn").html("重新上傳");
                $("#qiniu-upload-btn").attr("disabled",false);
            },
            'UploadProgress': function(up, file) {
            },
            'Error': function(up, err, errTip) {
                $("#qiniu-upload-btn").html("重新上傳");
                $("#qiniu-upload-btn").attr("disabled",false);
                alert("上傳失敗!請重試!");
            }
            ,
            'Key': function(up, file) {//在這裡可以改變檔案的名稱和路徑
                var key = "public/";
                var now = new Date();
                key += now.getFullYear().toString()+(now.getMonth()+1).toString()+"/"+now.getDate()+"/"+now.getHours()+"/";
                key += randStr()+".png";
                return key
            }
        }
    });
    uploader.bind('FileUploaded', function() {
        console.log('hello man,a file is uploaded');
    });
});
function randStr() {//這個是為了生成隨機字串用的
    var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    var n = 10, s = "";
    for(var i = 0; i < n; i++){
        var rand = Math.floor(Math.random() * str.length);
        s += str.charAt(rand);
    }
    return s;
}

photoClip截圖 生成Base64圖片

首先下載jQueryphotoClip外掛
然後引入js檔案,編寫html佈局
最後js實現
注:js程式碼中涉及到一個彈窗外掛layer,很簡單,引用一個js就行了。

html頁面

    <style>
        .load_mask{    position: absolute;  width: 100%;  height: 100%;  text-align: center;  padding-top: 30%;background-color: #fffeff;z-index: 100;opacity: 0.9;display: none;}
        #loadText{margin-top: 20px;font-size: 20px;}
        #img_show{position: fixed;width: 100%;height: 100%;top: 0;left: 0;background-color: #0c0c0c;z-index: 100;display: none;}
        #img_show .sn-operation-content{position: absolute;z-index: 99;text-align: center;width: 100%;bottom:10%;}
        #img_show .btn{margin: 0 10px;}
        .shunshizhen{    width: 30px;  height: 30px;  position: absolute;  z-index: 99;  color: #ffffff;  line-height: 30px;  font-size: 30px;  left: 48%;  top: 10%;}
    </style>
    <div class="load_mask">
        <img src="../images/icon/loading.gif" alt="" class="t_loadImg">
        <div id="loadText">圖片剪裁中...</div>
    </div>
    <div id="img_show">
        <div class="sn-operation-content">
            <a class="sn-photoclip-cancel btn btn-white">取消</a>
            <a class="sn-photoclip-ok btn btn-danger">選取</a>
        </div>
        <i class="icon-repeat shunshizhen"></i>
    </div>
    <div>
        <img id="image" src='{$gradeImg}' />
        <input type="hidden" id="qiniu-uptoken" value="{$QiniuToken}">
        <input type="hidden" id="qiniu-domain" value="{$QiniuDomain}">
        <input type="hidden" id="image_original" value="{$gradeImg}">
    </div>
    <!--截圖上傳-->
    <div id="mm-photoclip">
        <input type="file" id="file" accept="image/*" />
        <label for="file" class="btn btn-success">上傳</label>
    </div>
    <!--截圖上傳end-->
<script src="../common/layer/layer.min.js"></script>
<script src="../photoclip/iscroll-zoom.js"></script>
<script src="../photoclip/hammer.js"></script>
<script src="../photoclip/lrz.all.bundle.js"></script>
<script src="../photoclip/jquery.photoClip.js"></script>
<!--base64.js 和 upload_image.js 自己寫-->
<script src="../base64.js"></script>
<script src="../upload_image.js"></script>

upload_image.js

程式碼中有很詳細的註釋,就不解釋了
注:1、clipArea.shunshizhen();這個是圖片順時針的效果方法,要自己去改jquery.photoClip.js 檔案。因為這個不在文章的內容範圍,就不解釋了。
2、photoClip外掛有個相容性的問題,還是得自己去改。
3、putb64()這是一個上傳base64圖片到七牛雲的方法,後面會講。

var file_name;

$(function () {
    var obj;
    var clipArea = new bjj.PhotoClip("#img_show", {
        size: [200, 272], // 擷取框的寬和高組成的陣列。預設值為[260,260]
        adaptive: null, // 擷取框自適應,擷取框寬和高的百分比組成的陣列。預設為 null。如果設定了該引數,且值有效,則會忽略 size 的大小設定,size 中的值僅用於計算寬高比。當設定了其中一個值得百分比時,如果另一個未設定,則將會按 size 中的比例等比縮放。
        outputSize: [200,272], // 輸出影象的寬和高組成的陣列。預設值為[0,0],表示輸出影象原始大小
        outputType: "jpg", // 指定輸出圖片的型別,可選 "jpg" 和 "png" 兩種種類型,預設為 "jpg"
        outputQuality: .8, // 輸出質量,取值 0 - 1,預設為0.8。(這個質量不是最終輸出的質量,與 lrzOption.quality 是相乘關係)
        file: "#file", // 上傳圖片的<input type="file">控制元件的選擇器或者DOM物件
        source: "", // 需要裁剪圖片的url地址。該引數表示當前立即開始裁剪的圖片,不需要使用 file 控制元件獲取。注意,該引數不支援跨域圖片。
        view: "", // 顯示擷取後圖像的容器的選擇器或者DOM物件
        ok: ".sn-photoclip-ok", // 確認截圖按鈕的選擇器或者DOM物件
        loadStart: function(file) {
            obj = this;
            file_name = file.name;
            $(".load_mask").show();
            $("#loadText").html("圖片讀取中...");

        }, // 開始載入的回撥函式。this指向當前 PhotoClip 的例項物件,並將正在載入的 file 物件作為引數傳入(如果是使用 source 載入圖片,則該引數為圖片的 img 物件)
        loadComplete: function(img) {
            $("#img_show").fadeIn(250);
            $(".load_mask").hide();
            $("#loadText").html("圖片裁剪中...");
            $(".shunshizhen").unbind('click').bind("click",function(){
                clipArea.shunshizhen();
            });
        }, // 載入完成的回撥函式。this指向當前 PhotoClip 的例項物件,並將圖片的 img 物件作為引數傳入
        loadError: function(event) {
            show_error("截圖外掛出錯");
        }, // 載入失敗的回撥函式。this指向當前 PhotoClip 的例項物件,並將錯誤事件的 event 物件作為引數傳入
        clipFinish: function(dataURL) {
            // layerIndex1= layer.open({
            //     type: 2
            //     ,content: '圖片剪裁中'
            // });

            if(!navigator.onLine){
                layer.alert("網路不好,請檢查網路再上傳喲~");
                $("#img_show").fadeOut(250);
                return false;
            }
            $(".load_mask").show();


            putb64(dataURL);   //上傳base64圖片到七牛雲


            $("#img_show").fadeOut(250);
        }, // 裁剪完成的回撥函式。this指向當前 PhotoClip 的例項物件,會將裁剪出的影象資料DataURL作為引數傳入
        lrzOption: { // lrz壓縮外掛的配置引數
            width:500, // 圖片最大不超過的寬度,預設為原圖寬度,高度不設時會適應寬度。
            height: 500, // 圖片最大不超過的高度,預設為原圖高度,寬度不設時會適應高度。
            quality: 1 // 圖片壓縮質量,取值 0 - 1,預設為0.7。(這個質量不是最終輸出的質量,與 outputQuality 是相乘關係)
        }
    });
    $(".sn-photoclip-cancel").click(function() {
        $("#img_show").fadeOut(250);
    });
})

上傳base64 編碼圖片到七牛雲

官方有相應的說明:如何上傳base64編碼圖片到七牛雲
因為我這裡有個需求:修改KEY值,就是改變上傳檔案在七牛上的名字。
這裡說得很清楚,可以不用管uptoken.SaveKey , 直接在url後面加個欄位並且欄位要base64加密
官方說明

base64.js

js給字串進行base64編譯的。網上一搜一大把:

function str2Base64(str) {
    var b = new Base64();
    return b.encode(str);
}
function Base64() {

    // private property
    _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    // public method for encoding
    this.encode = function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;
        input = _utf8_encode(input);
        while (i < input.length) {
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
            output = output +
                _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
                _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
        }
        return output;
    }

    // public method for decoding
    this.decode = function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
        while (i < input.length) {
            enc1 = _keyStr.indexOf(input.charAt(i++));
            enc2 = _keyStr.indexOf(input.charAt(i++));
            enc3 = _keyStr.indexOf(input.charAt(i++));
            enc4 = _keyStr.indexOf(input.charAt(i++));
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
            output = output + String.fromCharCode(chr1);
            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
        }
        output = _utf8_decode(output);
        return output;
    }

    // private method for UTF-8 encoding
    _utf8_encode = function (string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";
        for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                utftext += String.fromCharCode(c);
            } else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            } else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }
        return utftext;
    }

    // private method for UTF-8 decoding
    _utf8_decode = function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;
        while ( i < utftext.length ) {
            c = utftext.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            } else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            } else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }
}

put64() 上傳base64圖片到七牛雲

和官方提供的一樣,只是修改了一下key值
方法randStr() 用於生成隨機的字串

function putb64(base){
    if(!navigator.onLine){
        layer.alert("網路不好,請檢查網路再上傳喲~");
        $(".load_mask").hide();
        return false;
    }
    var token = $("#qiniu-uptoken").val();
    var bases = base.split(";base64,");
    var pic = bases[1];
    var url = "http://upload.qiniu.com/putb64/-1"; //非華東空間需要根據注意事項 1 修改上傳域名
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange=function(){
        if (xhr.readyState==4){
            var result = eval('(' + xhr.responseText + ')');
            var key = result.key;
            $(".load_mask").hide();
            var image = $("#qiniu-domain").val()+key;
            $("#image_original").val(image);
            $("#image").attr("src",image);
            // success_upload(key,[]);

        }
    };
    var mm_key = "public/"+randStr()+".png";
    mm_key = str2Base64(mm_key);      //base64編譯
    mm_key = mm_key.replace("+","-"); 
    mm_key = mm_key.replace("/","_");
    url += "/key/"+mm_key;
    xhr.open("POST", url, true);
    xhr.setRequestHeader("Content-Type", "application/octet-stream");
    xhr.setRequestHeader("Authorization", "UpToken " + token);
    xhr.send(pic);
}
function randStr() {
    var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    var n = 10, s = "";
    for(var i = 0; i < n; i++){
        var rand = Math.floor(Math.random() * str.length);
        s += str.charAt(rand);
    }
    return s;
}