在前后端交互的项目当中,许多情况下我们需要上传和存储图片和文件等非文本信息。这些文件不能通过数据库进行存储,只能是存储在本地或者云端。本文将介绍Node.js后端如何将用户上传的文件存储在本地,并通过腾讯云对象存储转存在云端。

准备工作

      1.腾讯云sdk:npm i cos-nodejs-sdk-v5 –save
      2.静态资源上传:npm install –save @koa/multer multer

对象存储sdk文档
multer文档

使用koa/multer存储文件到本地

const multer = require('@koa/multer');
const Router = require('koa-router')
 
const router = new Router({ //设置前缀
    prefix: '/api'
});
 
 //磁盘存储引擎方法
 const storage = multer.diskStorage({
 	destination: (req, file, cb) => {
 		//存储前端传来的文件路径
 		cb(null, 'upload/image');
 	},
 	//更改文件名
 	filename: (req, file, cb) => {
 		// 通过split得到文件名的后缀
 		let fileFormat = (file.originalname).split('.');
		// 时间戳加随机数组合 得到新的文件名
 		let num =
 			`${Date.now()}-${Math.floor(Math.random(0,1)*10000)}${'.'}${fileFormat[fileFormat.length-1]}`;
 		cb(null, num);
 	}
 })
 const upload = multer({
 	storage
 });
 
//图片上传接口
router.post('/upload', upload.single('file'), async ctx => {
	console.log(ctx.file); //接收前端上传的静态资源文件:ctx.file
	ctx.response.body = '上传成功';   
	
        // 如果需要上传到腾讯云对象存储则使用以下代码(可选)
	// 同步上传至腾讯云对象存储
	try {
	     const res = await cloud(ctx.file.filename, ctx.file.path);
             // 将云端地址返回给前端
	     new result(ctx, 'SUCCESS', 200, 'https://' + res).answer();
	    } catch (e) {
	 	new result(ctx, '上传失败,服务器发生错误', 500).answer();
	    }
})
 
module.exports = router

上传文件至腾讯云对象存储(可选)

// 腾讯云对象存储sdk
const COS = require('cos-nodejs-sdk-v5');
var cos = new COS({
	SecretId, // 推荐使用环境变量获取;用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
	SecretKey, // 推荐使用环境变量获取;用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参考https://cloud.tencent.com/document/product/598/37140
	Protocol: 'https:', //使用协议
});
let Bucket = '';  //存储桶名称
let Region = 'ap-guangzhou';  //地区 这里我的是广州

//传入  存入到云存储的文件名  本地的文件路径
let cloud = function(filename, path) {
	return new Promise((resolve, reject) => {
		cos.uploadFile({
				Bucket,
				/* 填入您自己的存储桶,必须字段 */
				Region,
				/* 存储桶所在地域,例如 ap-beijing,必须字段 */
				Key: 'image/' + filename,
				/* 存储路径,必须字段 */
				FilePath: path,
				/* 必须 */
				
				// Body: Buffer.from(path),  //二进制上传
				//SliceSize: 1024 * 1024 * 5,     /* 触发分块上传的阈值,超过5MB使用分块上传,非必须 */
			})
			.then(res => {
				//console.log(res);
				resolve(res.Location);
			})
			.catch(err => {
				reject(err);
			})
	})
}