node开发一个图片服务器(koa) | 【图片优化】(三)
前言
一名正在自由职业的程序员的独立开发之路 每天100元的图片流量费用 逼得我不得不做图片优化 目前已经全部优化完成 希望我的经历能给你带来帮助 这是图片优化的第三篇
说明
本篇主要记录服务端如何实现一个图片服务器,并接入别人的CND
我这边用Nginx
实现图片服务,用Koa
实现图片的上传,用了一家服务商接入CND
这样虽然我的服务器只有 1M
的宽带,也能实现 每天60G
流量的暴击
是不是很6
下面是我服务器的配置
图片优化系列文章
- 每天100元的图片费用,就是我主动优化图片的动力 | 【图片优化】(一)
- 客户端优化(小程序+后台) | 【图片优化】(二)
- node开发一个图片服务器(koa) | 【图片优化】(三)
- 如何检测图片服务的性能 | 【图片优化】(四)(番外篇)
Nginx 实现图片服务(主要做静态服务)
用Nginx
来实现 图片的获取,主要有以下好处
- Nginx服务与图片上传的服务分离,确保稳定性,万一上传的那个
Node
服务崩了,咋办 Nginx
直接做静态服务器,应该比自己启的Node
服务应该更加稳定
Nginx配置如下(并配置HTTPS)
# 配置静态服务
server {
listen 80;
server_name abc.com;
#access_log logs/host.access.log main;
location / {
root /image/;
autoindex on;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 同时配置 HTTPS
server {
listen 443 ssl;
server_name abc;
ssl_certificate /cert/abc.pem;
ssl_certificate_key /cert/abc.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #按照这个协议配置
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;#按照这个套件配置
ssl_prefer_server_ciphers on;
location / {
root /image/;
autoindex on;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
用Koa实现图片上传
用Koa做图片上传有很多的中间件,也可以自己写
我一开始用的是 koa-body
,能实现自定义图片名字,但是无法根据前端传递的参数去自定义图片的名字,不符合我的需求
后来用的koa-multer
,其他的不太了解
直接上代码了
const multer = require("koa-multer");
# uploadDir 为上传到你的哪个目录
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, uploadDir);
},
filename: function (ctx, file, cb) {
const fileNameDate = dayjs().format("YYYYMMDD_HHmmss_SSS")
fileName = `${fileNameDate}_${file.originalname}`
if(ctx.body.prefix) fileName = `${ctx.body.prefix}_${fileName}`
# fileName 为重新命名的文件名,可以自定义
# prefix 这个参数是客户端传过来的
cb(null, fileName);
},
});
# 图片的配置
let upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 60, // 这样算下来就是 KB(限制在60K)
},
});
router.post("/uploadMulter", upload.single("file"), async (ctx) => {
try {
console.log("data", ctx.req.file.filename);
let basename = ctx.req.file.filename
let url = `http://abc/${basename}`
ctx.body = {
code: 200,
msg: "上传成功",
url,
};
} catch (error) {
ctx.body = {
code: 400,
msg: "上传失败",
};
}
});
对接CND
CDN有很多的厂家,但是我最后找了一个小公司,别问为什么,就是为了省钱
酷乐云
接入流程
第一步 解析一下TXT记录
第二步 解析 cname(最终你最后要用的CDN地址的域名)
比如用 cdn.baidu.com
来举例
我们将cdn.baidu.com
解析到 官网后台给你的一个 字符串
第三步 上传HTPPS的证书到后台
这个直接在阿里云后台,自己申请hpps证书下载下来
然后在后台将里面的 值分别传上去就行了
第四步 把 cdn.baidu.com
解析到 自己的服务器地址
即使跟上面 nginx
配置的 http的那个一模一样
server {
listen 80;
server_name cdn.baidu.com;
#access_log logs/host.access.log main;
location / {
root /image/;
autoindex on;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
最后遇到的问题
到了这一步
当你访问 https://cdn.baidu.com/111.jpg
,第一次这个链接还是转到你自己的服务器上面
这个时候CDN 服务器会自动把这个路径的资源 加载到它的各个节点的CDN服务器
当第二次访问 https://cdn.baidu.com/111.jpg
这个链接,就直接访问的CND服务器,不会再访问你自己的服务器了
这样就解决了自己服务器性能问题和宽带问题
这里有个坑
因为是小公司,它这需要加载好几次才能资源真正加载过去
当然它也提供直接手动去把资源同步过去,对于不太常变资源,还是很不错的
用七牛云备份,防止意外情况
因为还是不太放心,所以我把图片在七牛服务器也备份了一份,保险一点
直接读取相关URL
,然后批量上传到七牛服务器
下面直接放七牛的代码
node 获取token
npm i qiniu
node 生成token
var config = {
"AccessKey": "",
"SecretKey": "",
"Bucket": "",
"Port": ,
"UptokenUrl": "",
"Domain": ""
}
var mac = new qiniu.auth.digest.Mac(config.AccessKey, config.SecretKey);
var config2 = new qiniu.conf.Config();
// 这里主要是为了用 node sdk 的 form 直传,结合 demo 中 form 方式来实现无刷新上传
config2.zone = qiniu.zone.Zone_z2;
var options = {
scope: config.Bucket,
// deleteAfterDays: 1, 这个代表1天后自动删除
returnBody:
'{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}'
};
var putPolicy = new qiniu.rs.PutPolicy(options);
router.post("/getQiuniuToken", async (ctx) => {
try {
var token = putPolicy.uploadToken(mac);
ctx.body = {
code: 200,
token,
};
} catch (error) {
ctx.body = {
code: 400,
};
}
});
web上传
# web上传
npm i qiniu
/**
*
* 获取七牛上传的图片
* 1.现货区token
* 2.上传
*/
submitImgForQiniu(file){
return new Promise(async (resolve,reject)=>{
let resToken = await this.$api.getQiuniuToken()
console.log('resToken ===',resToken)
var putExtra = {customVars: {} };
var config = {
useCdnDomain: true,
disableStatisticsReport: false,
retryCount: 6,
region: qiniu.region.z2
};
var token = resToken.uptoken;
var domain = resToken.domain;
// let key = `${new Date().getTime()}-${(Math.random().toFixed(3)) * 1000}-${file.name}`
// 保持原来的名字
let key = `${file.name}`
putExtra.customVars["x:name"] = key.split(".")[0];
putExtra.customVars["x:year"] = '2023';
console.log('上传参数 ... key', key)
let observable = qiniu.upload(file, key, token, putExtra, config);
var subObject = {
next: (response) => {
console.log('next ...', response)
},
error: (error) => {
console.log('error ...', error)
reject()
},
complete: (res) => {
let url = `http://你七牛设置的域名/${res.key}`;
console.log('res ...', res)
console.log('url ...', url)
resolve({upload_url:url})
}
};
let subscription = observable.subscribe(subObject);
})
},
总结
完成了图片上传的服务端
虽然我的服务器不够我的业务量
但是根据自身业务的特点 ,并且借助CDN 目前每天的流量在50G
这是一个【图片优化】系列文章的【第三篇】
转载自:https://juejin.cn/post/7242596613749866557