照片處理
在瀏覽器上傳圖片與顯示
上傳照片與顯示比我想像中的複雜許多啊!之前主要都是處理簡單的json file來往,如今要處理檔案就沒這麼輕鬆了。
觀念與實作上有兩個部分要釐清:
- HTML5新支援的File與Blob API
HTML5增進了許多出色的功能,與檔案相關的部分就是上述兩個API,檔案可以透過`<input type="file">
向Local端索取資料,抓到後可以暫存在瀏覽器記憶體中。
Blob是一種類似檔案的資料暫存方式,而File則是基於Blob而擴充的功能,使用這兩個API在調用檔案部分就更加的方便了,不過處理檔案還有諸多的編碼方式,其中的轉換我也看得霧裡來霧裡去OTZ,所以就不再多家著墨。 詳見MDN文檔、黑暗執行緒 、html5rock - 如何預覽並裁剪圖片
我使用的是Croppie.js,功能簡單又好用,不過官方文件寫的略微簡陋,建議到他的github直接看源碼,copy and modify最實在。 Crop最後回傳的resp打印出來是base64編碼的格式,我直接用json格式封裝傳送。 以下是部分代碼$uploadCrop.croppie('result', { type: 'canvas', size: 'viewport' }).then(function (resp) { $uploadCrop.fadeOut("slow",function(){ $('#personalPorfile').attr('src',resp).fadeIn('slow'); $('#importBtn').fadeIn('fast'); $('#cropBtn').fadeOut('fast'); }); console.log(resp); $.ajax({ type: "POST", url: myURL + "/users/profile", data: {profile:resp}, success: function(data){ console.log(data); }, error: function(data){ console.log(data); } }); });
上傳至Server並儲存
如何上傳至Server也花了我不少時間才實做出來,主要有兩個部分要釐清: - 瀏覽器端的編碼選擇:在stackflow上有討論 為何二進制文件需要編碼傳輸,內容提到主要是因為有些protocol會誤認為二進制文件是執行的指令,所以編碼後傳輸就不會出問題
a. 使用POST and encrypted by multipart/form-data:
POST的Content-type主要決定內文主體的編碼方式,用法可參考POST encrypted機制,這是標準的上傳文件的方式,如果想在瀏覽器使用AJAX需要透過FormData的方式包裝資料(詳見MDN解說)在Node JS Server部 分可以用Express組織寫的multer模組。
b. 使用Base64編碼:
這也是我目前採用的方式,主要原因是我採用croppie.js裁剪圖片後回回傳base64格式的圖片,後來就乾脆直接以base64方式傳輸過去,之後NodeJS解析後就直接儲存起來。參考資料 如何轉碼與儲存檔案
上述兩種方式我都有試過,第一種的話我是用multer,很簡單就可以儲存檔案,而且有許多方便的擴展功能(etc. 命名檔案與儲存路徑等),客戶端推薦用PostMan先做測試。 第二種方式也蠻簡單的,就是透過轉碼在用fs模組把檔案存起來,以下代碼也是參考stackoverflow的解答。router.post('/profile',function (req, res, next) { console.log("upload image here"); console.log(req.authUser.account); var base64Data = req.body.profile.replace(/^data:image\/png;base64,/, ""); fs.writeFile("public/uploads/"+ req.authUser.account +".png", base64Data, 'base64', function(err) { if(err){ res.status(401).json("error"); }else{ res.status(201).json("success"); } }); })