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 直传。更多细节可参考阿里云官方文档或各来源的完整代码。

相关推荐
玫城14 小时前
[ VUE ] 封装通用数组校验组件,el-input内使用
前端·javascript·vue.js
南半球与北海道#18 小时前
前端打印(三联纸票据打印)
前端·vue.js·打印
董世昌4119 小时前
深入浅出 JavaScript 常用事件:从原理到实战的全维度解析
前端
满栀58519 小时前
分页插件制作
开发语言·前端·javascript·jquery
qq_4061761419 小时前
深入剖析JavaScript原型与原型链:从底层机制到实战应用
开发语言·前端·javascript·原型模式
开开心心_Every20 小时前
免费窗口置顶小工具:支持多窗口置顶操作
服务器·前端·学习·macos·edge·powerpoint·phpstorm
闲蛋小超人笑嘻嘻20 小时前
Vue 插槽:从基础到进阶
前端·javascript·vue.js
梦65020 小时前
Vue2 与 Vue3 对比 + 核心差异
前端·vue.js
tiandyoin21 小时前
给 MHTML 添加滚动条.mhtml
前端·chrome·html·mhtml
遗憾随她而去.21 小时前
前端大文件上传(切片并发/断点续传/秒传/WebWorker 计算Hash) 含完整代码
前端