1. 程式人生 > >使用base64進行移動端圖片上傳

使用base64進行移動端圖片上傳

之前搞微信上的圖片上傳,想直接通過介面上傳到自己的圖片伺服器,發現移動端瀏覽器上挺多坑的,使用最簡單的form-data形式好像不成。研究了一下,發現base64格式通用性較強。

base64編碼

base64是一種使用可列印字元來描述二進位制資料的方法。base64字符集共有64個字元,包括a-zA-Z0-9共62個,另外兩個符號為+和/。

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

由於26=64,因而該64個字元只能描述6bits的資料,換句話說,3個位元組有24bits,對應著4個base64字元。在做base64編碼時,一般要在位元組流最後補充一到兩個0,相應的,編碼完成後,要在base64串最後補充一到兩個=。

解碼

解碼就是根據base64串還原二進位制資料的過程。

圖片顯示

img標籤是可以直接顯示base64編碼的圖片,像下面這樣:

<img src="data:image/gif;base64,R0lGODlhAwADAIABAL6+vv///yH5BAEAAAEALAAAAAADAAMAAAIDjA9WADs=" />

圖片上傳

圖片上傳可以通過form-data/Blob物件等方式,但針對不同的瀏覽器可能會出現適配上的問題。

如果將圖片轉化為base64格式,得到的就是一個字串,可以通過POST上傳到伺服器。所有瀏覽器對POST方法肯定是支援的,這個辦法通用性比較強。美中不足的是,圖片通常比較大,POST請求本身對資料大小是沒有限制的,但是一般後臺會限制上傳資料大小

,這個時候就需要後臺配合,允許上傳較長資料。

在前端,可以使用FileReader得到本地圖片的base64編碼。程式碼如下:
HTML(圖片選擇框):

<input class="select" type="file" accept="image/*" onchange="change(this)">

js:

function change (obj) {
    if (!obj.files.length) return;
    if (obj.files.length > 1) {
        alert("只允許上傳一張圖片!");
        return
; } var file = obj.files[0]; var reader = new FileReader(); reader.onload = function () { var result = this.result; //data:base64 $.post('/upload', {'base64': result}, function(result) { }); }; reader.readAsDataURL(file); }

後端接收

後端使用connect-multiparty中介軟體。
安裝

npm install --save connect-multiparty

後端接收程式碼:

var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();

router.post('/', multipartMiddleware, function(req, res, next) {
    var base64Data = req.body.base64.replace(/^data:image\/.*;base64,/, "");//remove head
    var ext = req.body.base64.match((/^data:([A-Za-z-+\/]+);base64)[1]; 
    var target_path = 'out.' + ext;
    fs.writeFile(target_path, base64Data, 'base64', function(err) {
        if (!err) {         
            res.json({'msg':'success'});
        }
    });
});

至此,一個完整的前端圖片上傳完成。而且由於是採用了base64編碼來實現,包括微信、移動在內各個瀏覽器都能適應。

前端壓縮

在移動端,手機拍照圖片會比較大,可以使用canvas的toDataURL介面進行壓縮。
對於前端壓縮,可以參考此文,其程式碼也在github上。
為了應對IOS上canvas大小的限制,該程式碼採用了瓦片繪製,就是將原圖切割成一個一個的矩形來繪製的。在使用時候,邊界沒處理好,有些圖片壓縮後有明顯的痕跡
有時間的話,可以對此進行優化。

參考