圖片上傳方案詳解

凹凸不平發表於2019-02-16

以往用到圖片上傳功能都是直接使用現成的外掛,今天把其中用到的知識點整理一下。

知識點字典

  • input 標籤之 file 型別
  • FileReader 物件:讀取檔案
  • FileReader.readAsDataURL():將讀取的檔案轉換為 base64 編碼的字串
  • FormData 物件
  • 使用 axios 上傳

input 標籤之 file 型別

當設定 input 標籤 type 為 file 時,input 表現性狀為上傳檔案樣式

預設樣式

file-input 有如下屬性:

  1. accept
    指定選擇檔案型別的範圍。預設為所有檔案型別
    圖片為 accept=”image/*”
    檔案型別取值見MDN
  2. capture
    當檔案型別為圖片或視訊且在移動端時,此屬性才有意義。

    • capture = `user` 呼叫前置攝像頭
    • capture = `environment` 呼叫後置攝像頭
    • 不設定則為使用者自己選擇
  3. multiple
    一個 Boolean 值,如果存在,則表示使用者可以選擇多個檔案
  4. files
    返回一個 FileList,列出每個所選檔案物件。除非 multiple 指定了屬性,否則此列表只有一個成員。主要用於 JS 操作。
<!-- html -->
<input type="file" multiple id="imgLocal" accept="image/*" />
// js
let inp = document.querySelector(`#imgLocal`)
inp.onchange = function(e) {
  let fileList = document.querySelector(`#imgLocal`).files
  console.log(fileList) //files
}

FileReader 物件

我們用 FileReader 物件實現圖片預覽功能。

FileReader 物件允許 Web 應用程式非同步讀取儲存在使用者計算機上的檔案(或原始資料緩衝區)的內容,使用 File 或 Blob 物件指定要讀取的檔案或資料。

建構函式

new FileReader()

返回一個新構造的 FileReader。

屬性

  • FileReader.readyState
    表示 FileReader 狀態的數字,取值如下

    • 0:EMPTY/還沒有載入任何資料
    • 1:LOADING/資料正在被載入
    • 2:DONE/已完成全部的讀取請求
  • FileReader.result
    檔案的內容。該屬性僅在讀取操作完成後才有效。
  • FileReader.error

事件及方法

我們主要是用 FileReader.onload 事件及 FileReader.readAsDataURL() 方法,其他見MDN

  • FileReader.onload
    處理 load 事件。該事件在讀取操作完成時觸發
  • FileReader.readAsDataURL()
    開始讀取指定的 Blob 中的內容。一旦完成,result 屬性中將包含一個 data: URL 格式的字串以表示所讀取檔案的內容。
//繼續使用上文的fileList
let file = fileList[0]
const fileReader = new FileReader()
fileReader.readAsDataURL(file) //讀取圖片
fileReader.addEventListener(`load`, function() {
  // 讀取完成
  let res = fileReader.result
  // res是base64格式的圖片
})

我們將 DOM 上 img 的 src 設為讀取的結果即可實現預覽功能。

FormData 物件

FormData 物件的使用:

  1. 用一些鍵值對來模擬一系列表單控制元件:即把 form 中所有表單元素的 name 與 value 組裝成
    一個 queryString
  2. 非同步上傳二進位制檔案。

建構函式

new FormData()

返回一個新構造的 FormData。

方法

FormData 方法有很多。我們這裡只用了她的 append()方法

formData.append(name, value, filename)

  • name:屬性名
  • value:屬性值,在我們這裡則指 file 資料
  • filename:當第二個引數為 file 或 blob 時,告訴伺服器的檔名。Blob 物件的預設檔名是“blob”。File 物件的預設檔名 是檔案的檔名。
// 繼續使用上文的file
const formDate = new FormData()
formDate.append(`userPicture`, file, `1.jpg`)

使用 axios 上傳

主要是設定 header 中的 Content-Type

直接上程式碼

//繼續使用上文的formDate
let config = {
  headers: {
    `Content-Type`: `multipart/form-data`
  }
}
axios
  .post(`serverUrl`, formDate, config)
  .then(res => {
    console.log(res)
  })
  .catch(err => {
    console.log(err)
  })

axios 亦可 使用onUploadProgress監聽上傳進度,不再贅述。

其他

其他還有直接form表單提交檔案等方式,可能不太自由。諸位有興趣的可以看一下。

相關文章