在 Vue 项目中实现不经过后端服务器直接上传文件到阿里云 OSS,可通过以下几种方案实现。以下是综合各来源的最佳实践和注意事项:
方案一:使用 OSS SDK 直传(前端配置密钥,不推荐)
- 安装依赖
shell
npm install ali-oss --save
- 封装上传方法
在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;
}
}
- 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 临时凭证(推荐生产环境)
- 后端提供 STS 接口
后端通过阿里云 STS 服务生成临时访问凭证(AccessKeyId、AccessKeySecret、SecurityToken),并返回给前端。 - 前端动态获取凭证并上传
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;
}
优势:避免密钥暴露,凭证有效期可控。
方案三:服务端签名后直传
- 后端生成签名策略
后端根据 OSS 要求生成policy和signature,返回给前端。 - 前端通过表单提交
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,兼容性强。
关键注意事项
- 跨域配置
在阿里云 OSS 控制台配置跨域规则,允许POST、PUT方法,并设置允许来源(如*或具体域名)。 - 文件命名
避免文件名冲突,建议使用唯一标识(如 UUID + 时间戳):
js
const fileName = `${Date.now()}-${Math.random().toString(36).substring(2)}.${file.name.split('.').pop()}`;
- 大文件分片上传
使用multipartUpload方法处理大文件,支持进度回调:
js
const result = await client.multipartUpload(fileName, file, {
progress: (p) => console.log(`上传进度: ${(p * 100).toFixed(2)}%`)
});
- 取消上传
通过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 直传。更多细节可参考阿里云官方文档或各来源的完整代码。