返回
将照片从浏览器直接上传到阿里云 OSS 对象存储桶
前端
2024-01-28 08:50:16
导语
在《不是所有的 No 'Access-Control-Allow-Origin' header... 都是跨域问题》一文中,@ redbuck 同学评论道:“为啥图片不前端直接传 OSS ?后端只提供上传凭证,还省带宽内存呢。” 这番话点醒了我。是的,这样做显然更合理,因此有了本文。
目录
如何上传
为了实现图片从前端直接上传到阿里云 OSS,我们需要用到以下工具:
- Vue.js 作为前端框架
- Element UI 作为前端组件库
- Node.js 作为后端运行环境
- STS(Security Token Service)作为安全凭证服务
前端界面
前端界面使用 Vue.js 和 Element UI 构建。界面很简单,只有一个按钮,点击后可以打开文件选择器,选择要上传的图片。
上传原理
当用户点击按钮选择图片后,前端会将图片文件转换为二进制数据,然后发送到后端。后端使用 STS 服务生成一个临时凭证,并将其返回给前端。前端收到临时凭证后,就可以直接将图片上传到阿里云 OSS。
后端代码
后端代码使用 Node.js 编写。主要包括两部分:生成临时凭证和接收图片数据。
生成临时凭证的代码如下:
const STS = require('aliyun-sdk/sts');
const client = new STS({
accessKeyId: 'YOUR_ACCESS_KEY_ID',
accessKeySecret: 'YOUR_ACCESS_KEY_SECRET',
});
const policy = {
Version: '1',
Statement: [
{
Action: 'oss:*',
Resource: 'acs:oss:*:*:*',
Effect: 'Allow',
},
],
};
const request = {
DurationSeconds: 3600,
Policy: JSON.stringify(policy),
};
client.getFederationToken(request, (err, data) => {
if (err) {
console.error(err);
} else {
// 返回临时凭证
res.json({
AccessKeyId: data.Credentials.AccessKeyId,
AccessKeySecret: data.Credentials.AccessKeySecret,
SecurityToken: data.Credentials.SecurityToken,
Expiration: data.Credentials.Expiration,
});
}
});
接收图片数据的代码如下:
const multer = require('multer');
const oss = require('ali-oss');
const storage = multer.memoryStorage();
const upload = multer({ storage });
const client = new oss({
accessKeyId: 'YOUR_ACCESS_KEY_ID',
accessKeySecret: 'YOUR_ACCESS_KEY_SECRET',
});
app.post('/upload', upload.single('file'), (req, res) => {
const { file } = req;
const stream = client.putStream(file.originalname, file.buffer);
stream.on('error', (err) => {
console.error(err);
});
stream.on('success', () => {
res.json({
url: `https://${BUCKET_NAME}.oss-cn-hangzhou.aliyuncs.com/${file.originalname}`,
});
});
});
前端代码
前端代码使用 Vue.js 和 Element UI 编写。主要包括两个部分:选择图片和上传图片。
选择图片的代码如下:
<el-button @click="selectImage">选择图片</el-button>
<input type="file" @change="handleImageChange" hidden>
上传图片的代码如下:
handleImageChange(event) {
const file = event.target.files[0];
this.formData.append('file', file);
axios.post('/upload', this.formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
.then((res) => {
this.imageUrl = res.data.url;
})
.catch((err) => {
console.error(err);
});
}
注意事项
在使用本方法时,需要注意以下几点:
- 临时凭证的有效期是 3600 秒,因此需要在临时凭证过期前完成上传。
- 上传的文件大小不能超过 5GB。
- 上传的文件数量不能超过 1000 个。
- 上传的文件不能包含违法或违规内容。
总结
本文介绍了如何使用 Vue.js、Element UI 和 Node.js 将图片从前端直接上传到阿里云 OSS。这种方法可以降低带宽和内存消耗,提高上传效率。