Angular2 + NodeJs 上傳圖片到伺服器
一個小小的功能,花了接近一天的時間才搞定。網上雖然有很多關於Angular2 上傳圖片的部落格,但基本對我都幫助不大。大多數部落格的問題在於,他們只是貼了大段的程式碼,完全沒有強邏輯性的文字描述,大大提高了別人從部落格中學習的成本。可能甚至連他們自己都不清楚這個功能是怎麼實現的,為什麼這樣寫就能實現了。所以我每次寫部落格的時候都會先給出一個解決問題的步驟,然後再按步驟進行解決,並貼出相應的程式碼。這樣寫的好處是將問題拆分成一個個小問題進行解決,即使別人在參考你的部落格的過程中遇到了問題,也可以針對出問題的小點進行其他的搜尋,而不必否定整篇部落格,重新去看其他的部落格。閒話說到這裡,迴歸正題。
雖然接觸前端挺久的了,但是圖片上傳對我來說一直是一個黑盒似的操作。之前也基本是用表單進行提交,中間具體轉換成什麼,怎麼傳輸到伺服器一概不知。如果不用表單,也不知道該怎麼實現圖片上傳,當然不算微信這種提供了相應的api 的“框架”。直到這兩天研究angular + nodejs 上傳圖片的時候才想到一個問題:圖片是可以轉換成base64 編碼的,而base64 編碼就是一個字串,如此一來,那圖片上傳跟普通的ajax 請求不就沒什麼區別了嗎?
問題已經很清楚了,我們只要在前端構造一個物件,物件中存放個圖片的名字型別等資訊外加base64 編碼,然後把這個物件通過ajax 請求傳送給伺服器端即可,伺服器端接收到請求以後,拿出圖片的base64 編碼,還原為圖片,儲存到伺服器端的某一個路徑下,然後把該路徑返回給前端,即可完成圖片從瀏覽器端到伺服器端的傳輸操作。接下來,就是實操環節了。
1. 前端
首先,我們需要通過給html 的input 標籤繫結一個事件來獲取使用者選定的圖片的相關資訊,html 程式碼如下:
<input name="img" type="file" id="img-input" (change)="uploadImg($event)"/>
在js 的事件函式中取出圖片的資訊,放到我們構造的物件中,並將圖片轉換為base64 編碼,然後把相應的編碼同樣放入該物件中,圖片轉換為base64 編碼的程式碼也已經放在下面:
uploadImg(event) { const imgFile: File = event.target.files[0]; // post data const postData = { name: imgFile.name, size: imgFile.size, type: imgFile.type, base64: '' }; const a = new FileReader(); a.onload = (e) => { // 獲取base64 postData.base64 = e.target.result; // 上傳圖片 this.postService.uploadImg(postData) .subscribe(res => { if (res.code === 0) { // success code } else { // err code } }); }; a.readAsDataURL(imgFile); }
2. 後端
async uploadImg(req, res, next) {
// 獲得圖片base64
const imgData = req.body.base64;
const base64Data = imgData.replace(/^data:image\/\w+;base64,/, "");
const dataBuffer = new Buffer(base64Data, 'base64');
// 設定影象名
const imgName = req.body.name.split('.')[0] + '_' + Date.parse(new Date())
+ '.' + req.body.name.split('.')[1];
let result = {
code: 0,
msg: 'ok',
data: {}
}
// 儲存圖片
fs.writeFile('upload_img/' + imgName, dataBuffer, function(err) {
if(err){
result.code = -1;
result.msg = 'error';
}else{
result.code = 0;
// 返回圖片位置
result.data.url = 'http://localhost/angularBlogBk/upload_img/' + imgName;
}
res.send(JSON.stringify(result));
});
}