返回

将照片从浏览器直接上传到阿里云 OSS 对象存储桶

前端

导语

在《不是所有的 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。这种方法可以降低带宽和内存消耗,提高上传效率。