返回 导航

其他

hangge.com

Vue3 - Supabase的集成与使用详解5(文件的上传、下载、管理、分享)

作者:hangge | 2024-02-28 09:26
    Supabase StorageSupabase 提供的一项服务,它允许用户在云端存储和管理文件,比如图像、音频、视频等。使用 Supabase Storage,我们可以轻松地上传、下载、管理和分享文件,而无需操心底层的服务器配置和维护。

五、文件的上传、下载、管理、分享

1,创建 bucket 存储桶

(1)这里我们通过 Supabase Dashboard 控制台创建存储桶,首先我们创建一个名为 images 的公开存储桶:

(2)接着对这个存储桶进行安全策略配置:

(3)为方便演示,这里我们设置所有用户(无论是否登录),都可以对文件进行上传、下载、删除等各种操作。
提示:关于用户权限的详细设置与使用,可以参考我之前写的文章(点击查看

2,样例代码

下面代码我们利用 Supabase Storage 实现文件的上传、替换、删除、下载和预览等功能:
提示:文件保存到本地我使用的是 FileSaver 库,可以通过 npm install file-saver 命令进行安装。
<script setup>
import { ref, onMounted } from 'vue'
import { supabase } from './lib/supabaseClient'
import { saveAs } from 'file-saver'

const bucketName = 'images' // 存储桶名称
const folderName = 'test' // 文件夹
const files = ref([]) // 用于存储文件列表的引用
const fileInput = ref(null) // 文件输入元素的引用
let isReplace = false // 标志位,用于判断是否替换文件

// 获取文件列表
async function getFiles() {
  const { data, error } = await supabase.storage.from(bucketName).list(folderName);
  if (error) {
    console.error('获取文件列表失败', error.message);
  } else {
    files.value = data;
  }
}

// 触发文件输入元素的点击事件
function triggerFileInput(value) {
  isReplace = value
  // 调用fileInput的点击事件
  fileInput.value.click()
}

// 处理文件选择变化事件
function handleFileChange(event) {
  const selectedFile = event.target.files[0];  
  if (selectedFile) {
    // 根据isReplace标志位选择上传或替换文件
    if (isReplace) {
      replaceFile(selectedFile)
    } else {
      uploadFile(selectedFile)
    }   
  }
  fileInput.value.value = ''
}

// 上传文件
async function uploadFile(file) {
  const { data, error } = await supabase.storage.from(bucketName)
    .upload(`${folderName}/${file.name}`, file);
  if (error) {
    console.error('文件上传失败', error.message);
  } else {
    console.log('文件上传成功', data);
    await getFiles();
  }
}

// 替换文件
async function replaceFile(file) {
  const { data, error } = await supabase.storage.from(bucketName)
    .update(`${folderName}/${file.name}`, file);
  if (error) {
    console.error('文件替换失败', error.message);
  } else {
    console.log('文件替换成功', data);
    await getFiles();
  }
}

// 删除最后一个文件
async function deleteLastFile() {
  if (files.value.length > 0) {
    const lastFile = files.value[files.value.length - 1];
    const { error } = await supabase.storage.from(bucketName)
      .remove(`${folderName}/${lastFile.name}`);
    if (error) {
      console.error('文件删除失败', error.message);
    } else {
      console.log('文件删除成功')
      await getFiles();
    }
  }
}

// 下载最后一个文件
async function downloadLastFile() {
  if (files.value.length > 0) {
    const lastFile = files.value[files.value.length - 1];
    const { data, error } = await supabase.storage.from(bucketName)
      .download(`${folderName}/${lastFile.name}`)
    if (error) {
      console.error('文件下载失败', error.message)
    } else {
      console.log('文件下载成功', data)
      // 使用FileSaver库将文件保存到本地
      const blob = new Blob([data])
      saveAs(blob, lastFile.name)
    }
  }
}

// 预览最后一个文件
function previewLastFile() {
  if (files.value.length > 0) {
    const lastFile = files.value[files.value.length - 1];
    // 获取文件链接,可以在新窗口中打开或通过浏览器支持的预览方式
    const fileLink = supabase.storage.from(bucketName)
      .getPublicUrl(`${folderName}/${lastFile.name}`);
    console.log('文件链接', fileLink.data.publicUrl)
  }
}

// 组件挂载时获取文件列表
onMounted(() => {
  getFiles();
});
</script>

<template>
  <div>
    <!-- 使用 input[type="file"] 元素进行文件选择 -->
    <input type="file" ref="fileInput" style="display: none" @change="handleFileChange" />
    <!-- 通过按钮触发文件选择 -->
    <button class="action-button" @click="triggerFileInput(false)">上传文件</button>
    <button class="action-button" @click="triggerFileInput(true)">替换文件</button>
    <button class="action-button" @click="deleteLastFile">删除最后一个文件</button>
    <button class="action-button" @click="downloadLastFile">下载最后一个文件</button>
    <button class="action-button" @click="previewLastFile">预览最后一个文件</button>
  </div>

  <!-- 新增显示文件列表的无序列表 -->
  <ul class="file-list">
    <li v-for="file in files" :key="file.id">
      {{ file.name }}
    </li>
  </ul>
</template>

<style scoped>  .action-button {
    margin-right: 5px; /* 设置按钮之间的外边距 */
  }

  .file-list {
    margin-top: 20px;
    padding: 0;
  }

  .file-list li {
    margin-bottom: 8px;
  }
</style>

3,运行测试 

(1)页面打开后点击“上传文件”按钮可以进行文件上传,上传后会自动加载显示所有的文件列表。 

(2)访问 Supabase Dashboard 控制台也可以看到我们上传的文件。

(3)相同文件夹下同名文件无法重复上传,点击“替换文件”按钮,选择一个新文件,会将原来的同名文件替换为新文件,同样会自动刷新文件列表。

(4)点击“删除最后一个文件”按钮,会删除最后上传的文件,并更新文件列表。

(5)点击“下载最后一个文件”按钮,会下载最后上传的文件到本地。下载成功后,文件将保存在浏览器默认下载路径中。

(6)点击“预览最后一个文件”按钮,会在控制台输出最后上传文件的公开链接。

  • 我们可以使用这个链接在新窗口中打开文件或者通过浏览器支持的预览方式查看文件内容。
评论

全部评论(0)

回到顶部