html5 實現簡單的上傳

簡單記錄下今早作H5上傳中一些代碼還有坑css

1、展現html

由於前端上傳文件是必須經過form表單的,不能使用ajax,這樣的話一個移動頁面放入一個type爲file的input真心不怎麼好看,以下圖,很挫有沒有前端

解決辦法找了下,PC上有些是把這個input換成flash,採用jquery的工具庫好比uploadify來作,可是移動端大部分瀏覽器是不支持flash的。因此最後採用的辦法仍是用form表單的形式,只是把這個form和input的透明度設置爲0,讓它們和準備顯示的內容同時在一個div中,顯示的內容能夠作成本身想要的樣子。代碼以下:html5

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
        <title></title>
        <style>
            div{width: 100%;}
            .logo img{display:block; margin:0 auto;}
            .upload{position: relative;width: 80px;height: 18px;line-height: 18px;background: #2fc7c9;text-align: center;
                    color: #FFF;padding: 0px 5px;-webkit-border-radius: 2px;border-radius: 2px;
                    margin: 0 auto;
                    }
            .upload form{width:100%;position:absolute; left:0; top:0;opacity:0; filter:alpha(opacity=0);}
            .upload form input{width: 100%;}
        </style>
    </head>
    <body>
        <div class="logo">
            <img src="img/1.jpg" />
        </div>
        <div class="upload">
            <p>上傳圖片</p>
            <form>
                <input type="file" />
            </form>
        </div>
    </body>
</html>

樣子如左圖,這樣展示就在「上傳圖片」這個p標籤中,點擊它就有選擇file的效果jquery

 

2、JS代碼web

我這邊寫的蠻簡單的,只是用了下h5上傳的的基本功能ajax

html代碼以下,action爲要請求的路徑,我這邊作的是當文件發生改變時就上傳修改頭像,input標籤的name屬性不能省去,具體跟後端接口有關canvas

<form id="uploadForm" enctype="multipart/form-data" method="post" action="XXXXXX">
     <input type="file" name="imageFile" id="imageFile" onchange="fileSelected()" />
</form>
var iMaxFilesize = 2097152; //2M
window.fileSelected = function() {
    var oFile = document.getElementById('imageFile').files[0];    //讀取文件
    var rFilter = /^(image\/bmp|image\/gif|image\/jpeg|image\/png|image\/tiff)$/i;
    if (!rFilter.test(oFile.type)) {
        alert("文件格式必須爲圖片");
        return;
    }
    if (oFile.size > iMaxFilesize) {
        alert("圖片大小不能超過2M");
        return;
    }
    var vFD = new FormData(document.getElementById('uploadForm')),    //創建請求和數據
        oXHR = new XMLHttpRequest();
    oXHR.addEventListener('load', function(resUpload) {
        //成功
    }, false);
    oXHR.addEventListener('error', function() {
        //失敗
    }, false);
    oXHR.addEventListener('abort', function() {
        //上傳中斷
    }, false);
    oXHR.open('POST', actionUrl);
    oXHR.send(vFD);
};

 

3、圖片壓縮後端

在開發中,特別是在移動端每每一張圖片大小在3,4M左右,這樣的圖片上傳會給服務器帶來很多壓力,同時也有很多接口對img的大小有所要求,好比不能超過200K,那手機相冊的照片大可能是見了鬼的,都上傳不了。在html5的功能中,能夠將圖片壓縮大小(尺寸)放到canvas畫布上,而後截取canvas畫布上的圖片,轉變爲二進制的數據,經過blob進行再次壓縮生成圖片文件,這樣手機上4M左右圖片傳到服務器上也就100K左右了。數組

<input type="file" name="imageFile" id="imageFile" onchange="fileSelected()" />
<form id="uploadForm" enctype="multipart/form-data" method="post" action="XXXXXX">
     <input hidden="hidden" name="param" value="test" />
</form>

當文件改變時,對圖片進行壓縮上傳

window.fileSelected = function() {
    var _this = $(this);
    var file = this.files[0];
    var rFilter = /^(image\/bmp|image\/gif|image\/jpeg|image\/png|image\/tiff)$/i;
    if(!rFilter.test(file.type)) {
        alert("文件格式必須爲圖片");
        return;
    }
    /*開始進行網絡加載*/
    _this.css("display", "none");    //目的是爲了屏蔽點擊事件
    var reader = new FileReader() , image = new Image() ,
        canvas = document.createElement("canvas") , ctx = canvas.getContext("2d");
    reader.onload = function() {        //文件加載完成
        var url = reader.result;
        image.src = url;
    };
    image.onload = function() {        //圖片加載完成
        var w = image.naturalWidth , h = image.naturalHeight ,
            scale = 3;        //圖片縮放比例,這裏是把圖片大小高寬均縮小3倍
        canvas.width = w / scale;
        canvas.height = h / scale;
        ctx.drawImage(image, 0 , 0 , w , h ,
            0 , 0 , canvas.width , canvas.height);
        fileUpload();    
    };
    reader.readAsDataURL(file);        //用文件加載器加載文件
    function fileUpload() {        //文件上傳方法
        var quality = 0.3;        //圖片的質量,這裏設置的是0.3
        var data = canvas.toDataURL("image/jpeg", quality);//獲取畫布圖片,而且要jpg格式
        data = data.split(',')[1];
        data = window.atob(data);
        var ia = new Uint8Array(data.length);
        for(var i = 0; i < data.length; i++) {
            ia[i] = data.charCodeAt(i);
        }
        var blob = new Blob([ia], {            //以上均爲二進制參數處理,從而獲取一個blob對象
            type: "image/jpeg"
        });
        var fd = new FormData(document.getElementById("uploadForm"));
        fd.append("XXX"  , blob , "upload.jpg");    //向form中加入圖片數據,name屬性是XXX,文件名是upload.jpg
        var xhr = new XMLHttpRequest();
        xhr.addEventListener('load', function(resUpload) {
            _this.css("display", "");
            //請求成功
        }, false);
        xhr.addEventListener('error', function(){
            _this.css("display", "");
            //請求失敗
        }, false);
        xhr.addEventListener('abort', function(){
            _this.css("display", "");
            //上傳終止
        }, false);
        xhr.open('POST', "http://XXXXXXXXXXXXX");//請求地址
        xhr.send(fd);//發送
    }
};

關鍵代碼

reader.readAsDataURL(file);

將文件讀取爲DataURL

canvas.toDataURL(type, encoderOptions); 

實際上就是讀取canvas畫布上圖片的數據。其默認是png格式,若是第一個參數type是image/jpeg的話,第二個參數encoderOptions就能夠用來設置圖片的壓縮質量。

var quality = 0.3;        //圖片的質量,這裏設置的是0.3
var data = canvas.toDataURL("image/jpeg", quality);//獲取畫布圖片,而且要jpg格式
data = data.split(',')[1];
data = window.atob(data);
var ia = new Uint8Array(data.length);
for(var i = 0; i < data.length; i++) {
    ia[i] = data.charCodeAt(i);
}
var blob = new Blob([ia], {            //以上均爲二進制參數處理,從而獲取一個blob對象
    type: "image/jpeg"
});

這一段代碼的的目的是爲了解碼圖片數據,而後返回一個Blob對象,對象的格式是jpg。aton其做用是作解碼,由於圖片格式的base64,該方法解碼出來多是一堆亂碼,Uint8Array返回的是8進制整型數組。

Blob是存儲二進制文件的容器,典型的Blob對象是一個圖片或者聲音文件,其默認是PNG格式。最後的blob就能夠傳給服務端了。

整理成一個插件,代碼以下

(function(window,undefind){
    function imgUpLoad(options){
        var defaults = {
            inputId : "" ,        //輸入框ID
            formId : "" ,        //表單ID
            paramName : "" ,        //輸入框的name
            requestUrl : "" ,     //請求的URL
            imgSizeScale : 3 ,     //圖片縮放比例
            imgQuality : 0.3 ,    //圖片質量
            sucFun : undefind , //成功的回調函數
            errFun : undefind , //失敗的回調函數
            abortFun : undefind     //上傳取消的回調函數
        };
        var opts = $.extend(true , defaults , options || {}) ,
            _this = document.getElementById(opts.inputId);
        _this.addEventListener('change' , fileChange , false);    
        function fileChange() {
            var file = _this.files[0];
            var rFilter = /^(image\/bmp|image\/gif|image\/jpeg|image\/png|image\/tiff)$/i;
            if(!rFilter.test(file.type)) {
                alert("文件格式必須爲圖片");
                return;
            }
            var reader = new FileReader() , image = new Image() ,
                canvas = document.createElement("canvas") , ctx = canvas.getContext("2d");
            startFileLoad(reader , image , canvas , ctx);
        }
        function startFileLoad(reader , image , canvas , ctx){    //文件加載
            reader.onload = function() {        //文件加載完成
                var url = reader.result;
                image.src = url;
            };
            image.onload = function() {        //圖片加載完成
                var w = image.naturalWidth , h = image.naturalHeight;
                canvas.width = w / opts.imgSizeScale;
                canvas.height = h / opts.imgSizeScale;
                ctx.drawImage(image, 0 , 0 , w , h ,
                    0 , 0 , canvas.width , canvas.height);
                fileUpload(canvas);    
            };
            reader.readAsDataURL(file);    
        }
        function fileUpload(canvas){        //文件上傳
            var blob = getBlob(canvas);
            var fd = new FormData(document.getElementById(opts.formId));
            fd.append(opts.paramName  , blob , "upload.jpg");
            var xhr = new XMLHttpRequest();
            xhr.addEventListener('load', function(resUpload) {    //請求成功
                _this.style.display = "";
                if(opts.sucFun && typeof opts.sucFun === "function")        opts.sucFun(resUpload.currentTarget.response);
            }, false);
            xhr.addEventListener('error', function(){    //請求失敗
                _this.style.display = "";
                if(opts.errFun && typeof opts.errFun === "function")        opts.errFun();
            }, false);
            xhr.addEventListener('abort', function(){    //上傳終止
                _this.style.display = "";
                if(opts.abortFun && typeof opts.abortFun === "function")        opts.abortFun();
            }, false);
            xhr.open('POST', opts.requestUrl);//請求地址
            xhr.send(fd);//發送
        }
        function getBlob(canvas){        //獲取blob對象
            var data = canvas.toDataURL("image/jpeg", opts.imgQuality);
            data = data.split(',')[1];
            data = window.atob(data);
            var ia = new Uint8Array(data.length);
            for(var i = 0; i < data.length; i++) {
                ia[i] = data.charCodeAt(i);
            }
            return new Blob([ia], {            
                type: "image/jpeg"
            });
        }
    }
    window.imgUpLoad = imgUpLoad;
})(window);
相關文章
相關標籤/搜索