iT邦幫忙

2021 iThome 鐵人賽

DAY 18
1
Modern Web

Vue.js 進階心法系列 第 18

用兩支 API 實作新增資料與上傳檔案

實作新增資料與上傳檔案有兩種做法

  1. 開一支 API 處理新增使用者,設定成 multipart/form-data 就可以同時上傳檔案和使用者資料。
  2. 開一支上傳檔案的 API,處理檔案,另一支就處理要儲存到資料庫的使用者資料。上傳之後的 path 放在資料庫的任務就交給了前端。

在講的是第二種方法,想要在 POST User 時,先上傳大頭照,再把 path 放到使用者資料。

之後會專門寫一篇文章,講「多個動作的同步資料整理」。

API 文件

遇到這種 API,怎麼做呢?

POST /user/:id

request body

{
  name: 'chris',
  avatar: 'http://127.0.0.1/img/user_1.jpg'
}

**response 200 **

(略)

POST /file

request header

{
  'Content-Type': 'multipart/form-data'
}

request body

form-data

{
  file: (binary)
}

**response 200 **

{
  data: '/file/:file_path'
}

依照 API 文件寫 vuex

依前幾天建立的默契,可以知道

  1. state 要建立 file
  state: {
    file: null
  },
  1. mutations 要建立 file
  mutations: {
    file(state, payload) {
      state.file = payload
    }
  },
  1. getters 要建立 file
  getters: {
    file: state => state.file
  },

這些一定要做。

  1. 避免直接存取資料
  2. 需要時可以擋住格式不符
  3. 可以使用 devtool 的 hook
  4. 增加資料的抽象化

另外特別的地方

  1. 資料直送的情況,mutation 和 getters 的命名要相同。
  2. 資料有特別處理,會增加不同名字的 getters。

所以

要 file 可以用 $store.getters.file 就取得

@/store/actions.js

import backendAPI from '@/utility/backendAPI.js'

export default {
  async uploadFile({ commit, getters }) {
    const file = getters.file;
    const res = await backendAPI.formDataPOST(`/file`, { file })
    return res.data
  }
  // ...
}

src/store/user/actions.js

在 createUser 上面加上 uploadFile

import backendAPI from '@/utility/backendAPI.js'

export default {
  async createUser({ dispatch, getters }, { name }) {
    if (getters.file != null) {
  	  const res = await dispatch('uploadFile');
      await backendAPI.POST(`/user`, {
        name,
        avatar: res.data,
      });
    } else {
      await backendAPI.POST(`/user`, {
        name,
      });
    }
  },
  // ...
}

在新增時就可以直接

    onSubmit() {
      this.$store.dispatch('createUser', this.$store.getters.user);
    }

另一種不推薦的做法

直接在選取完檔案之後,就將檔案先上傳。而不是等到要新增人員時才上傳。

缺點: 在一次修改的過程中,不斷的換掉檔案,就會不斷的上傳,導致伺服器上的垃圾檔案會更新變多。


上一篇
actions 就是 Vuex 裡「共用的 method」
下一篇
載入頁面,什麼時候發 API 適合?
系列文
Vue.js 進階心法30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言