当前位置: 首页 > 后端技术 > Node.js

Node实现github图床向阿里云Oss的自动搬运

时间:2023-04-04 01:30:50 Node.js

Node实现github图床到阿里云oss的自动传输就我而言,去他妈的生意,不要钱。我在挣扎(pin)战斗(qiong),我只能把代码写好。跑题了,我想说说原因。最近越来越觉得github慢,各种pullpush都卡,家里的github网站也很慢,博文打开,各种图片破解;现在我不仅用vscode写代码,还用来写文章,写笔记。所以尝试为自己创造一个舒适的书写工具是非常重要的。以前都是用segmentfault和github做自己的镜像云,可惜免费总是要价的。一直在用githubissue写文章,终于忍不住了。我想换画床。机智的我,去年有活动的时候,不仅买了3年的229服务器,还花45元买了个oss仓库。vscode本地图床插件:Picgo用来上传文件到github,然后复制地址到vscode文件。最近想自己写一个插件,让vscode可以直接上传图片到oss。百度一下,发现自己真的落伍了,找了个插件Picgo,用的是阿里云oss,贴上个人的vscode配置:红色标记的选项很重要。配置好后截图,cmd+option+u,马上就能感受到vscode插画的快感。历史文章图片处理受不了github图片随时破解,打开慢。既然已经有了oss,那我们就全部替换吧,但是这么多文章(40+)和笔记(60+),一张一张复制,cmd键肯定是空白的。我懒,我绝对不会,我绝对不会用这么粗暴的方法。太机智了,写了一个基于NodeJs的小工具。技术栈(Node):fs+http+Oss-Sdk原理:遍历文章源文件,读取图片地址,标记;下载图片,上传到oss,获取新的图片地址;使用新的图像地址位置更新标记;更新文件;代码(涉及较多的正则匹配和风骚操作,不懂请忽略):constpath=require('path');constfs=require('fs');constutil=require('util');consthttps=require("https");consthttp=require("http");conststream=require('stream');constoss=require('./oss');//注意:方案测试通过;constisExists=util.promisify(fs.exists);constreadFile=util.promisify(fs.readFile);constwriteFile=util.promisify(fs.writeFile);constreg=/\!\[[\s\S]{3,20}\]\((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?\)/G;consturlReg=/(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;consttypeReg=/http.*(?=\.[jpg,png,jpeg,gif])/;constHasReg=/http.*\.(jpg|png|jpeg|gif)$/;consthttpReg=/^http:.+/;constBUcket_Dir='article';functiongetRadomName(){constrandomCode=Math.地板(数学。随机()*26)+65;返回rn`${Date.now()}-${String.fromCharCode(randomCode)}`;}constconfig={accessKeyId:'你的id',accessKeySecret:'你的秘密'};constoss=newOss()函数httpGet(url,enable,check){returnnewPromise((resolve,reject)=>{constmethod=httpReg.test(url)?http:https;method.get(url,(res)=>{constchunks=[];letsize=0;enable&&console.log('start');if(check){if(res.statusCode!=200){resolve('none');}else{resolve(url);}return;}if(res.statusCode==301){resolve('move');}res.on('data',(data)=>{//收集获取到的文件流//console.log('trans',data.length);chunks.push(data);size+=data.length;});res.on('end',()=>{//文件流拼接获取bufferenable&&console.log('结束',大小);解决(Buffer.concat(块,大小));});})})。catch((error)=>{console.error(error);});}asyncfunctiongetImage({url,dir}){//判断url是否有图片类型标识,然后生成新的图片地址let目标;if(url.indexOf('user-images.githubusercontent.com')>1){url=url.replace('https://user-images.githubusercontent.com','http://github-production-user-asset-6210df.s3.amazonaws.com');constarr=url.split('/');target=`${dir}${arr[arr.length-1]}`;constossUrl=`https://doddle.oss-cn-beijing.aliyuncs.com/${target}`;//检查文件是否已经上传constcheckExsit=awaithttpGet(ossUrl,true,true);if(checkExsit===ossUrl){返回ossUrl;}}else{target=HasReg.test(url)?url.replace(typeReg,`${dir}${getRadomName()}`):`${dir}${getRadomName()}.png`;}//获取缓冲区constbuffer=awaithttpGet(url,true);//如果发生错误,将不替换地返回原始地址;if(!buffer){console.log('错误发生');返回网址;}//如果响应是301,直接返回原地址if(buffer==='move'){returnurl;}//生成一个临时文件流,并将Buffer写入流中constfileSream=newstream.PassThrough();fileSream.end(缓冲区);//上传,并获取存储的urlconstresult=awaitoss.uploadStream(target,fileSream);返回结果.url;}asyncfunctionreplaceUrl(file,name){constdir=`${BUcket_Dir}/${name?名称:file.replace('.md','')}/`;constfilePath=path.resolve(__dirname,'../arcticle/',文件);constisExist=awaitisExists(文件路径);//oss只初始化一次;如果(!oss.init){oss.create(config);}//判断目标文件是否存在;if(!isExist){console.log('文件:',文件,'不存在');返回;}//读取文件内容constcontent=awaitreadFile(filePath,'utf8');让计数=0;常量队列=[];//内容替换;constcon=content.replace(reg,(str)=>{//oss北京,不用替换if(str.indexOf('doddle.oss-cn-beijing')>0){returnstr;}consturl=str.slice(str.indexOf('(')+1,str.length-1);//占位符常量地址=`url-${count}-end`;queue.push({url,dir});//安慰.log('new',newUrl);计数++;//先把目标Url替换成站点符号,再进行下一步;返回str.replace(urlReg,地址);});//根据原始url,获取对应的ossurlconstres=awaitPromise.all(queue.map((param)=>getImage(param)));//console.log('count',count,res);计数=0;//根据Responseurl数组,替换站号constfinal=con.replace(/url-[\d]+-end/g,function(){returnres[count++];});//反向写入文件awaitwriteFile(filePath,final,{encoding:'utf-8'});console.log('finishthefile:',file);}fs.readdir('./arcticle',(err,files)=>{//console.log('file',files.length);files.forEach((file)=>{//console.log('file',file);replaceUrl(file,'shim');});})原理其实很简单,没多久就搞定了实现了,但是还是花了很多时间,因为github在国内被封了,但是我这种情况你可能不会遇到,比如:不过我聪明,把https链接换成http,我发现图片也可以访问了,但是用Node发起http请求的时候,发现响应是301,再看浏览器,发现确实是重定向了所以这是代码:if(url.indexOf('user-images.githubusercontent.com')>1){url=url.replace('https://user-images.githubusercontent.com','http://github-production-user-asset-6210df.s3.amazonaws.com');}上面代码注释的很详细,有不懂的可以留言。附加Oss封装代码:constOSS=require('ali-oss');module.exports=classMyOss{constructor(){this.client=null;this.upload=this.upload.bind(this);this.uploadStream=this.uploadStream.bind(this);this.getList=this.getList.bind(this);这个。初始化=假;}//初始化Clientcreate({accessKeyId,accessKeySecret}){this.client=newOSS({bucket:'doddle',region:'oss-cn-beijing',accessKeyId,accessKeySecret,secure:true,//设置为true,返回的url才是https的});这个。初始化=真;}asyncupload({file,key,options={}}){try{constresult=awaitthis.client.put(key,file,options);返回结果;}catch(e){console.log(e);返回假;}}asyncuploadStream(name,file){try{constresult=awaitthis.client.putStream(name,file);返回结果;}catch(e){console.log(e);返回假;}}asyncgetList(dir=''){试试{constresult=awaitthis.client.list({prefix:dir});返回结果;}catch(e){console.error(e);返回假;}}}