1. 程式人生 > >Angular2 + NodeJs 上傳圖片到伺服器

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));
  });
}