FireBase(体验)结合upload实现IMG/Video上传

118 阅读2分钟

About Firebase

Firebase 是由 Google 提供的一套云端服务,旨在帮助开发者构建高质量的移动应用和网站。它提供实时数据库、身份验证、云存储、云函数、托管、实时消息推送、分析等多种功能,使开发者能够更轻松地构建、部署和管理应用,而无需过多关注底层基础设施。Firebase 的目标是简化开发流程,提高开发效率。

首先,确保你的项目已经集成了 Firebase SDK。如果还没有,可以在 Firebase 控制台中创建一个新项目并按照文档中的指南添加 Firebase 到你的应用中。接下来,打开 Firebase 控制台并导航到你的项目。在左侧导航栏中选择“Storage”选项,这是 Firebase 云存储的主要设置页面。

准备工作

首先,确保你的 Vue.js 项目已经设置好 Firebase。你可以使用 Vue CLI 或其他方式创建一个新项目,并在项目中安装 Firebase:

npm  i  firebase

设置 Firebase 云存储

在 Firebase 控制台中,选择“Storage”并按照向导设置云存储。你可以指定存储桶的规则以及默认的文件存储位置。

在 Vue.js 中配置 Firebase

在 Vue.js 项目中,你需要配置 Firebase 并初始化它。 utils/firebase.ts 文件,添加以下代码:

// 添加你的 Firebase 配置信息
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getStorage } from "firebase/storage";
// import { getAnalytics } from "firebase/analytics";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
  appId: "YOUR_APP_ID"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const storage = getStorage(app)
// const analytics = getAnalytics(app);


创建上传组件

现在,我们将创建一个 Vue 组件,允许用户上传文件。在 src 文件夹下创建一个新的组件文件,比如 FileUploader.vue


<template>
  <div>
    <el-upload ref="uploadRef" :auto-upload="false" class="upload-demo" drag :before-upload="beforeUpload"
      :on-success="handleSuccess" :on-error="handleError" :http-request="customHttpRequesthandler" multiple>
      <el-icon class="el-icon--upload"><upload-filled /></el-icon>
      <div class="el-upload__text">
        Drop file here or <em>click to upload</em>
      </div>
      <template #tip>
        <div class="el-upload__tip">
          <!-- 根据需要添加提示信息 -->

          <el-button class="ml-3" type="success" @click="submitUpload">
            upload to server
          </el-button>
        </div>
      </template>
    </el-upload>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import {
  UploadFilled
} from '@element-plus/icons-vue'
import { customHttpRequest } from '@/util/firebaseUploader'; // 替换为你的具体路径
import type { UploadInstance } from 'element-plus'
const uploadRef = ref<UploadInstance>()
const files = ref<File[]>([]);
const beforeUpload = (file: File) => {
  // 在这里添加你的文件验证逻辑
  files.value.push(file);
  // return false; // 禁止 el-upload 组件自动上传
};
const handleSuccess = () => {
  console.log("success");
  // el-upload 组件的成功回调留空,因为我们手动处理了上传逻辑
};
const handleError = (error: any) => {
  console.error(`文件上传失败: ${error.message}`);
};

const customHttpRequesthandler = async () => {
  try {
    const urls = await customHttpRequest(files.value);
    console.log(urls); // 这里可以使用返回的URL列表进行后续操作
  } catch (error) {
    console.error(error);
  }

}

// 手动上传
const submitUpload = () => {
  uploadRef.value!.submit()
}
// firebase


</script>

<style lang="less" scoped></style>

对应的upload的function

// firebaseUploader.ts
import { storage } from "./firebase"; // 替换为你的 firebase.ts 文件路径
import { ref as storageRef, uploadBytesResumable, getDownloadURL, UploadTaskSnapshot } from 'firebase/storage';

interface FileUploadResult {
  fileName: string;
  downloadURL: string;
}

export const customHttpRequest = async (files: File[]): Promise<FileUploadResult[]> => {
  if (files.length === 0) {
    return [];
  }

  const uploadPromises: Promise<FileUploadResult>[] = files.map(storeImage);

  try {
    const uploadResults = await Promise.all(uploadPromises);
    return uploadResults; // 返回图片的 URL 列表,以供后续使用
  } catch (error: any) {
    throw new Error(`文件上传失败:${error.message}`);
  }
};

const storeImage = (file: File): Promise<FileUploadResult> => {
  return new Promise((resolve, reject) => {
    const fileName = `${new Date().getTime()}_${file.name}`;
    const newStorageRef = storageRef(storage, fileName);
    const uploadTask = uploadBytesResumable(newStorageRef, file);

    uploadTask.on(
      'state_changed',
      (snapshot: UploadTaskSnapshot) => {
        const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
        console.log(`上传进度:${progress.toFixed(2)}%`);
      },
      (error) => {
        reject(error);
      },
      () => {
        getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
          const result: FileUploadResult = {
            fileName,
            downloadURL,
          };
          resolve(result);
        });
      }
    );
  });
};