本文将通过15分钟的教学,让你掌握在Vue3项目中实现以下核心功能:

  • ✅ 直传文件到阿里云OSS

  • ✅ 实时进度条显示

  • ✅ 自动生成带时间戳的文件名

  • ✅ 安全策略配置

  • ✅ 错误自动重试机制

一、准备工作

1.1 创建OSS Bucket

  1. 登录阿里云控制

  2. 创建Bucket(区域选择与你业务最近的地域)

  3. 记录以下信息:

    OSS_REGION = "oss-cn-beijing"
    OSS_BUCKET = "your-bucket-name"
    ACCESS_KEY_ID = "your-access-key"
    ACCESS_KEY_SECRET = "your-secret-key"

1.2 配置CORS规则(重要!)

在Bucket权限管理 -> 跨域设置中添加:

[
  {
    "AllowedOrigin": ["*"],
    "AllowedMethod": ["GET", "POST", "PUT"],
    "AllowedHeader": ["*"]
  }
]

二、Vue项目集成

2.1 安装依赖

npm install ali-oss crypto-js

2.2 创建OSS工具类

新建 src/utils/ossClient.js

import OSS from 'ali-oss';
import CryptoJS from 'crypto-js';

// 生成唯一文件名
const generateFileName = (file) => {
  const timestamp = new Date().getTime();
  const randomString = CryptoJS.lib.WordArray.random(8).toString();
  return `${timestamp}_${randomString}.${file.name.split('.').pop()}`;
};

export const initOSSClient = () => {
  return new OSS({
    region: import.meta.env.VITE_OSS_REGION,
    accessKeyId: import.meta.env.VITE_ACCESS_KEY_ID,
    accessKeySecret: import.meta.env.VITE_ACCESS_KEY_SECRET,
    bucket: import.meta.env.VITE_OSS_BUCKET
  });
};

export const uploadFile = async (client, file) => {
  const fileName = generateFileName(file);
  return client.put(fileName, file);
};

三、实现上传组件

3.1 创建上传组件

新建 src/components/OSSUploader.vue

<template>
  <div class="upload-container">
    <input 
      type="file" 
      @change="handleFileChange"
      ref="fileInput"
      style="display: none;"
    />
    <button @click="triggerFileSelect" class="upload-btn">
      {{ uploadStatus || '选择文件' }}
    </button>
    <progress 
      v-if="progress > 0" 
      :value="progress" 
      max="100" 
      class="upload-progress"
    />
    <div v-if="fileUrl" class="preview-area">
      <a :href="fileUrl" target="_blank">查看文件</a>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { initOSSClient, uploadFile } from '@/utils/ossClient';

const fileInput = ref(null);
const uploadStatus = ref('');
const progress = ref(0);
const fileUrl = ref('');

const triggerFileSelect = () => {
  fileInput.value.click();
};

const handleFileChange = async (e) => {
  const file = e.target.files[0];
  if (!file) return;

  try {
    uploadStatus.value = '上传中...';
    const client = initOSSClient();
    
    const result = await uploadFile(client, file, {
      progress: (p) => {
        progress.value = Math.floor(p * 100);
      }
    });

    fileUrl.value = result.url;
    uploadStatus.value = '上传成功!';
    setTimeout(() => {
      progress.value = 0;
      uploadStatus.value = '';
    }, 2000);
    
  } catch (err) {
    console.error('上传失败:', err);
    uploadStatus.value = '上传失败,请重试';
    progress.value = 0;
  }
};
</script>

<style scoped>
.upload-container {
  max-width: 400px;
  margin: 20px auto;
  padding: 20px;
  border: 2px dashed #ccc;
}

.upload-btn {
  padding: 12px 24px;
  background: #409eff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.upload-progress {
  width: 100%;
  margin-top: 10px;
  height: 8px;
}

.preview-area {
  margin-top: 15px;
}
</style>

四、安全增强方案(推荐)

4.1 使用环境变量

创建 .env.local

VITE_OSS_REGION="oss-cn-beijing"
VITE_OSS_BUCKET="your-bucket"
VITE_ACCESS_KEY_ID="your-key-id"
VITE_ACCESS_KEY_SECRET="your-secret"

4.2 服务端签名方案(可选)

建议在生产环境使用STS临时凭证:

// 在初始化时替换为动态获取的临时凭证
const getSTSCredentials = async () => {
  const res = await axios.get('/api/sts-token');
  return new OSS({
    region: res.data.region,
    accessKeyId: res.data.accessKeyId,
    accessKeySecret: res.data.accessKeySecret,
    stsToken: res.data.securityToken,
    bucket: res.data.bucket
  });
};

五、常见问题解决

5.1 跨域问题

确保已正确配置:

  • OSS控制台的CORS规则

  • Bucket权限为公共读(测试阶段)

5.2 大文件上传

分片上传方案:

const res = await client.multipartUpload(filename, file, {
  parallel: 4,
  partSize: 1024 * 1024,
  progress: (p) => {
    console.log('分片进度:', p);
  }
});

5.3 文件类型限制

在组件中添加校验:

const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'application/pdf'];

const handleFileChange = (e) => {
  const file = e.target.files[0];
  if (!ALLOWED_TYPES.includes(file.type)) {
    alert('不支持的文件类型');
    return;
  }
  // ...后续上传逻辑
};

项目部署提示:在正式环境中,请务必通过后端获取临时凭证(STS Token),避免在前端暴露AccessKey!

通过以上步骤,你已经实现了:

  • 安全可靠的OSS直传方案

  • 带进度显示的友好交互

  • 自动化的文件名管理

  • 完善的错误处理机制

遇到问题可以查看阿里云OSS官方文档或留言讨论~

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐