基于对象存储服务实现本地资源上传

1,121 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

平时在做个人项目的时候需要上传一些静态资源(图片,音频,文件等),之前的项目在部署到服务器上后是单独创建一个文件夹来存放一些上传的文件,后面也是存在一些问题,比如访问的时候很卡,有些比较大的图片加载也会很慢,导致这些问题是因为个人的云服务器配置太低,而且有些文件不想因为压缩后清晰度变低就保持原来的大小上传的,这样也会消耗内存。后面了解了下可以使用云存储的方式来对静态资源进行上传。

对象存储

对象存储(Object-based storage),也叫作基于对象的存储,用来描述解决和处理对象。对象在一个层结构中不会再有层级结构,是以扩展元数据为特征的。

常见的一些对象存储平台有:腾讯云的对象存储服务(COS), 阿里云的对象存储服务(OSS), 华为云的对象存储服务(OBS) 等等。

对象存储服务的优势及使用

相比传统的服务器存储资源, 对象存储具有高扩展性、低成本、可靠安全等优点。具体的一些特点和相关概念可以参考三大云平台中对该产品的详细介绍,下面就对腾讯云的对象存储做一下简单的使用然后结合 node 服务来实现文件上传。

准备工作

开通对象存储服务,创建存储桶, 配置相关信息

第一次进入会让开通 COS服务,然后创建存储桶

01.png

02.png

创建好了进入存储桶,可以看到存储桶类似一个磁盘,可以创建文件夹,上传文件,操作文件等,这里我创建了一个 image 文件夹,后面用于存放资源。

03.png

到这里差不多就完成存了存储桶的创建, 然后就是上传文件到这个'容器'中。

案例

这里使用 node + koa 搭建后台服务,需要安装 multer 来接收处理前段传来的文件, cos-nodejs-sdk-v5, nodeJS SDK 来操作存储桶

npm i @koa/multer multer cos-nodejs-sdk-v5 --save

cos.js: 处理本地文件,上传到存储桶中

const multer = require('@koa/multer');
const path = require("path");
const COS = require('cos-nodejs-sdk-v5');
const { resolve } = require('path');


var cos = new COS({
    SecretId: 'xxxxxxxxxxxxxx',
    SecretKey: 'xxxxxxxxxxxxxxxx',
    Protocol: 'https:'
});


let Bucket = 'zsp-scan-ordering-1259475950';    // 存储桶名称
let Region = 'ap-chengdu';     // 存储桶所在地域
let cosfun = async (filename, path) => {
    return new Promise((resolve, reject) => {
        cos.uploadFile({
            Bucket,
            Region,
            Key: 'image/' + filename,
            FilePath: path
        })
            .then(res => {
                resolve(res.Location)
            })
            .catch(err => {
                reject(err)
            })
    })

}

/*
    配置上传文件文件
        1. 所在的目录
        2. 更改文件名
*/

// 磁盘存储引擎
const storage = multer.diskStorage({
    // 存储前端传来的文件
    destination: (req, file, cb) => {
        // 文件夹必须是绝对路径,否则会报错: ENOENT:no such file or directory
        cb(null, path.join(__dirname, '../upload/image'))
    },
    filename: (req, file, cb) => {
        // 防止文件重名, 重新对文件命名
        let fileArr = (file.originalname).split('.')
        let fileFormat = `${Date.now()}-${Math.floor(Math.random() * 1E9)}.${fileArr[fileArr.length - 1]}`
        cb(null, fileFormat)
    }
})

const upload = multer({ storage })

module.exports = { upload, cosfun }

在使用 COS 方法时的 options 参数中有几个字段需要获取:SecretId, SecretKey, Bucket, Region, 也是必须传的字段

SecretId 和 SecretKey 合称为云 API 密钥,是用户访问腾讯云 API 进行身份验证时需要用到的安全凭证, 在上传资源时携带在参数中, 作为身份凭证,在 密钥管理 中获取

04.png

05.png

上面用的是主账号的 api 密钥,为了安全可以创建一个子用户,使用子用户的密钥,创建后需要对其授权,让子用户也能够使用 COS 服务

06.png

07.png

Bucket 和 Region 为存储桶名称和存储桶所在地域, 在存储桶列表中可以获取

uploadFile.js: 引用 cos.js 文件, 创建文件上传路由

const router = require('koa-router')();
const { upload, cosfun } = require('../../cos/cos');
const ReturnResult = require('../../config/returnResult');

// 图片上传接口 name:'file'
router.post('/uploadres', upload.single('file'), async ctx => {
    // 接收前端上传的静态资源
    try {
        // 调用 cosfun 方法, 上传成功会返回图片的地址, 可直接访问
        const res = await cosfun(ctx.file.filename, ctx.file.path)
        // 上传成功就返回图片地址给前端
        new ReturnResult(ctx, 'SUCCESS', 200, 'https://' + res).answer()
    } catch (error) {
        new ReturnResult(ctx, '上传失败, 服务器错误', 500).answer()
    }
})

测试

这里使用 postman 来对该接口进行测试。

08.png

可以看到文件上传成功后返回给前端当前文件的访问地址

去存储桶中可以看到上传的图片,点击详情可以看到图片的详细信息

09.png

10.png

最后, 案例中只是对普通文件进行上传, 没有做大小限制, 图片处理(添加水印等), COS 对象存储的一些其他用法可参考官方文档:

COS对象存储文档: cloud.tencent.com/document/pr…