1. 程式人生 > 其它 >vue3.0+TS+egg 前後端實現圖片上傳功能

vue3.0+TS+egg 前後端實現圖片上傳功能

技術標籤:vue

上效果圖
在這裡插入圖片描述
在這裡插入圖片描述


upload.vue

(樣式是boostrap,不必要太在意樣式,可以自己寫)

<template>
  <div class="file-upload">
    <div class="file-upload-container" @click.prevent="triggerUpload">
      <slot v-if="fileStatus === 'loading'" name="loading"
> <button class="btn btn-primary" disabled>正在上傳...</button> </slot> <slot v-else-if="fileStatus === 'success'" name="uploaded"> <button class="btn btn-primary">上傳成功</button> </slot> <
slot v-else name="default"> <button class="btn btn-primary">點選上傳</button> </slot> </div> <input type="file" class="file-input d-none" ref="fileInput" @change="handleFileChange"
> </div> </template> <script lang="ts"> import axios from 'axios'; import { defineComponent, ref } from "vue"; type UploadStatus = 'ready' | 'loading' | 'success' | 'error' export default defineComponent({ props: { action: { type: String, required: true } }, setup(props) { const fileInput = ref<null | HTMLInputElement>(null) const fileStatus = ref<UploadStatus>('ready') const triggerUpload = () => { if (fileInput.value) { fileInput.value.click() } } const handleFileChange = (e: Event) => { const currentTarget = e.target as HTMLInputElement if (currentTarget.files) { fileStatus.value = 'loading' const files = Array.from(currentTarget.files) const formData = new FormData() formData.append('file', files[0]) axios.post(props.action, formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(res => { console.log(res) fileStatus.value = 'success' }).catch(() => { fileStatus.value = 'error' }).finally(() => { if (fileInput.value) { fileInput.value.value = '' } }) } } return { fileInput, triggerUpload, handleFileChange } } }) </script>

使用元件的時候,傳入相對應的後端介面,即可

<Upload :action="'/api/upload'"></Upload>

egg

public 下,新建一個 comfiles 資料夾
router.js

router.post('/upload', controller.upload.uploadFiles);

app/controller/upload.js

'use strict';

const Controller = require('egg').Controller;

class UploadController extends Controller {
  async uploadFiles() {
    const { ctx } = this;
    const data = await ctx.service.upload.index();
    if (data) {
      ctx.body = data;
    } else {
      ctx.body = {
        message: '上傳失敗',
      };
    }
  }
}

module.exports = UploadController;

app/service/upload.js

'use strict';
const Service = require('egg').Service;
const fs = require('fs');
const path = require('path');
const sendToWormhole = require('stream-wormhole');


class UploadService extends Service {
  async index() {
    const ctx = this.ctx;
    const stream = await ctx.getFileStream();
    const fileName = stream.filename;

    const target = path.join(this.config.baseDir, `app/public/comfiles/${stream.filename}`);
    const result = await new Promise((resolve, reject) => {
      const remoteFileStream = fs.createWriteStream(target);
      stream.pipe(remoteFileStream);
      let errFlag;
      remoteFileStream.on('error', err => {
        errFlag = true;
        sendToWormhole(stream);
        remoteFileStream.destroy();
        reject(err);
      });

      remoteFileStream.on('finish', async () => {
        if (errFlag) return;
        resolve({ fileName, name: stream.fields.name });
      });
    });
    return result;
  }
}

module.exports = UploadService;

參考文章:https://www.cnblogs.com/qq735675958/p/9315694.html