iT邦幫忙

0

筆記- Vue透過Laravel 簡單上傳圖片/檔案

久久寫一次檔案上傳都要再去爬文?,乾脆自己筆記起來!!

一、Vue 前端

1. 隱藏Input的按鈕

HTML內建的上傳Input很醜,所以我都把它隱藏起來,要用時再自己手動去觸發他。為了觸發他因此要給他一個 ref 的值,這樣我們才能透過 $refs 直接去接觸DOM

原本的Input

<input type="file" style="display: none" ref="fileInput" >

2. 自己做一個上傳按鈕

這邊我是用 Quasar 框架的按鈕,用原生的 buttonCSS 也是可以啦。主要是讓他看起來像上傳的按鈕就好~這邊要做的事情就是按下去讓他去觸發原本按下 Input 時的事件。

<q-btn @click="$refs.fileInput.click()">上傳檔案</q-btn>

3. 觸發上傳事件

選擇好檔案後為了要讓他能觸發上傳的事件,這邊要再改一下剛剛的 Input,要在後面補上 v-on:change

<input type="file" style="display: none" ref="fileInput" @change="uploadFile()">

4.上傳事件的Function

接著再底下的 script 裡的 methods 新增一個上傳的方法。對了,這裡會透過 Axios 來把檔案丟給 Laravel。

<template>
  <q-page class="flex flex-center">
    <q-btn @click="$refs.fileInput.click()">上傳檔案</q-btn>
    <input type="file" style="display: none" ref="fileInput" @change="uploadFile">
  </q-page>
</template>

<script>
import axios from 'axios'
export default {
  methods: {
    uploadFile () {
      // 拿取檔案
      const file = this.$refs.fileInput.files[0]
      // 然後自己建立一個表單來放要上傳的資料
      // 也可以順便帶其他資料例如 userId
      const form = new FormData()
      form.append('file', file)
      form.append('userId', 'test1234')

      // 上傳到後端伺服器
      axios.post('https://後端網址', form)
    }
  }
}
</script>

二、Laravel 後端

這邊要用到 Laravel 內建的 Storage 功能,所以我們在一個 Controller 的最上面引入他:

use Illuminate\Support\Facades\Storage;

之後開始來處理剛剛丟進來的檔案(這邊假設Router都設定好了)

1.首先在 Controller 裡面開一個 function

public function postFile (Request $req) {}

2.我們剛剛的 file 會跑到 $req[‘file’] 這邊

像是圖片的話可以直接用 Storageput 方法存就好,因為他會幫我們把檔名變成亂數,可以不用花時間再去寫怕檔名重複的Code。這裡只要給他要儲存的路徑就好。

$storagePath = Storage::put('/public', $req['file']);

要知道剛剛程式自己存的檔名是什麼,可以透過 basename 去拿檔名:

$fileName = basename($storagePath);

而亂數的檔名會像這樣:
61DsAms1VuHcMq1wcFx7S8cEHJA86SwoHPTTRUZV.png

3.檔案存去哪裡!?

路徑不填的話檔案會存在 storage/app 底下
如果要讓其他人可以從網站存取那就要建立一個與 public 的超連結

php artisan storage:link

這樣在 public/storage 底下就可以看到 storage/app/public 底下的東西囉
所以要從網站上看剛剛上傳的網址就會是

https://你的Laravel網址/storage/剛剛上傳的檔名

4. 完整的程式碼

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;

class FileController extends Controller
{    
    public function postFile (Request $req) {
        $storagePath = Storage::put('/public', $req['file']);
        $fileName = basename($storagePath);
        // 接下來可以把檔名存進資料庫等等
        // ...
    }
}

*本文章同步發表於medium


1 則留言

0
愛的code
iT邦新手 4 級 ‧ 2021-07-24 18:43:54

請教一下博主:
在下拜讀您的文章覺得很值得學習,不過我試著依樣畫葫蘆時,卻遇到控制台一直報錯。
主要就是@click="$refs.fileInput.click()"這一段
報錯內容:

[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'imageInput' of undefined"

有空麻煩教導一下

已經解決!謝謝!

我要留言

立即登入留言