vue 上传文件到 OSS

在 Vue 项目中实现不经过后端服务器直接上传文件到阿里云 OSS,可通过以下几种方案实现。以下是综合各来源的最佳实践和注意事项:


方案一:使用 OSS SDK 直传(前端配置密钥,不推荐)

  1. 安装依赖
shell 复制代码
npm install ali-oss --save
  1. 封装上传方法
    utils/oss.js 中创建客户端实例并封装上传逻辑:
js 复制代码
import OSS from 'ali-oss';
const client = new OSS({
  region: 'oss-cn-hangzhou', // 替换为你的区域
  accessKeyId: 'your-access-key-id', // 阿里云 AccessKeyId
  accessKeySecret: 'your-access-key-secret', // 阿里云 AccessKeySecret
  bucket: 'your-bucket-name' // OSS 存储桶名称
});
export async function uploadFile(file) {
  try {
    const fileName = `uploads/${file.name}`; // 自定义文件路径
    const result = await client.put(fileName, file);
    return result.url; // 返回文件访问地址
  } catch (error) {
    console.error('上传失败:', error);
    throw error;
  }
}
  1. Vue 组件调用
html 复制代码
<template>
  <input type="file" @change="handleUpload" />
</template>
<script>
import { uploadFile } from '@/utils/oss.js';
export default {
  methods: {
    async handleUpload(event) {
      const file = event.target.files[0];
      const url = await uploadFile(file);
      console.log('文件地址:', url);
    }
  }
};
</script>

注意:此方案需在前端暴露密钥,存在安全风险,仅适用于测试环境。


方案二:STS 临时凭证(推荐生产环境)

  1. 后端提供 STS 接口
    后端通过阿里云 STS 服务生成临时访问凭证(AccessKeyIdAccessKeySecretSecurityToken),并返回给前端。
  2. 前端动态获取凭证并上传
js 复制代码
import OSS from 'ali-oss';
import axios from 'axios';
async function uploadWithSTS(file) {
  // 1. 请求后端获取临时凭证
  const { data } = await axios.get('/api/sts-token');
  
  // 2. 使用临时凭证初始化 OSS 客户端
  const client = new OSS({
    region: data.region,
    accessKeyId: data.accessKeyId,
    accessKeySecret: data.accessKeySecret,
    stsToken: data.securityToken,
    bucket: data.bucketName
  });
  // 3. 上传文件
  const result = await client.put(`uploads/${file.name}`, file);
  return result.url;
}

优势:避免密钥暴露,凭证有效期可控。


方案三:服务端签名后直传

  1. 后端生成签名策略
    后端根据 OSS 要求生成 policysignature,返回给前端。
  2. 前端通过表单提交
js 复制代码
async function uploadWithSignature(file) {
  const { data } = await axios.get('/api/oss-signature'); // 获取签名信息
  const formData = new FormData();
  formData.append('key', `uploads/${file.name}`);
  formData.append('policy', data.policy);
  formData.append('OSSAccessKeyId', data.accessId);
  formData.append('signature', data.signature);
  formData.append('file', file);
  const res = await axios.post(data.host, formData, {
    headers: { 'Content-Type': 'multipart/form-data' }
  });
  return `${data.host}/${formData.get('key')}`; // 返回文件地址
}

适用场景:无需 SDK,兼容性强。


关键注意事项

  1. 跨域配置
    在阿里云 OSS 控制台配置跨域规则,允许 POSTPUT 方法,并设置允许来源(如 * 或具体域名)。
  2. 文件命名
    避免文件名冲突,建议使用唯一标识(如 UUID + 时间戳):
js 复制代码
const fileName = `${Date.now()}-${Math.random().toString(36).substring(2)}.${file.name.split('.').pop()}`;
  1. 大文件分片上传
    使用 multipartUpload 方法处理大文件,支持进度回调:
js 复制代码
const result = await client.multipartUpload(fileName, file, {
  progress: (p) => console.log(`上传进度: ${(p * 100).toFixed(2)}%`)
});
  1. 取消上传
    通过 client.cancel() 中断上传任务。

方案对比

方案 安全性 适用场景 依赖
SDK 直传 低(密钥暴露) 测试环境 ali-oss
STS 临时凭证 生产环境 ali-oss + 后端接口
服务端签名直传 兼容旧项目 无 SDK

完整示例(STS 方案)

html 复制代码
<template>
  <el-upload
    action="#"
    :http-request="customUpload"
    :show-file-list="false"
  >
    <el-button>选择文件</el-button>
  </el-upload>
</template>
<script>
import OSS from 'ali-oss';
import axios from 'axios';
export default {
  methods: {
    async customUpload({ file }) {
      try {
        // 异步获取临时凭证
        const { data } = await axios.get('/api/sts-token');
        
        // 初始化 OSS 客户端
        const client = new OSS({
          region: data.region,
          accessKeyId: data.accessKeyId,
          accessKeySecret: data.accessKeySecret,
          stsToken: data.securityToken,
          bucket: data.bucketName
        });
        // 上传并获取地址
        const result = await client.put(`uploads/${file.name}`, file);
        this.$message.success(`上传成功: ${result.url}`);
      } catch (error) {
        this.$message.error('上传失败');
      }
    }
  }
};
</script>

根据安全需求选择方案:生产环境优先使用 STS 临时凭证服务端签名,测试环境可简化为 SDK 直传。更多细节可参考阿里云官方文档或各来源的完整代码。

相关推荐
我是伪码农8 分钟前
Vue 2.3
前端·javascript·vue.js
夜郎king33 分钟前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
夏幻灵2 小时前
HTML5里最常用的十大标签
前端·html·html5
Mr Xu_2 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝2 小时前
RBAC前端架构-01:项目初始化
前端·架构
程序员agions2 小时前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发2 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
程序员猫哥_2 小时前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞052 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
我爱加班、、2 小时前
Websocket能携带token过去后端吗
前端·后端·websocket