当前位置: 首页 > 科技观察

30分钟教你用NodeJs开发自己的图床应用

时间:2023-03-12 08:53:21 科技观察

前言本文主要回顾作者的nodeJS,通过一个在线的实际案例总结节点生态的常用技术点和最佳实践。以实战为主输出3个nodeJs项目需要一个月左右。本文为第一篇,主要介绍如何使用nodeJs开发图床应用。该项目对于测试和个人服务网站非常实用,可以在此基础上扩展更强大的应用。本文的图床项目主要是使用Koa开发的。不熟悉的可以先研究一下koa官网,或者看一下作者之前写的nodeJS文章。您将学习Node应用程序的基本架构和开发NodeJS应用程序的过程。Koa+Koa-Router+glob+Node基础API使用。介绍跨域方案KoaCors的使用,以及如何与前者跨域协作。基于@koa/multer打包文件上传中间件。使用React开发前端应用和xui的基本使用。Text首先,图床应用要保证我们的图片资源在不同域下可以访问,不存在跨域问题,并且可以支持不同域下的应用上传图片到图床,如下图:结合上图我们可以先做应用需求分析:以上是对像床应用的一个非常简单的需求分析。接下来,我们将构建项目结构并基于此分析开发我们的应用程序。在开始之前,我们先看一下简单的实现效果:访问和上传图片。获取图片链接地址。删除图片的显示界面只是一个例子。我们可以通过前端的方式设计自己的图床管理界面。这里提供的公共API可以在任意域名下调用,没有跨域问题。前台地址:基于xi搭建的图床界面前台。API开放地址:图床开放地址(免费,请勿破解)。1.Node应用的基本架构和NodeJS应用的开发过程。关于nodejs的项目架构以及如何组织nodejs目录,30分钟教你优雅搭建nodejs开发环境和目录设计。这篇文章中有详细的说明。您在阅读完本文后,可以进行学习和研究。开发任何应用程序之前要做的第一件事是了解需求。需求明确后,就可以进行技术选型了。开发基于nodeJS的后端应用有很多技术方案。如果熟悉nodejs,可以使用原生nodejs开发应用;对于中小型应用,我们可以直接使用Koa进行开发,它的中间件机制和插件化的设计理念可以让我们非常方便的开发自己的中间件;如果涉及比较复杂的业务线,我们可以使用egg.js或者nest.js作为nodeJS的框架选择。由于本文的图床应用比较简单,作者直接使用koa生态进行开发。接下来看看我们的图床应用的目录结构:2.Koa+Koa-Router+glob+NodeBasicAPI学习koa最快的方法就是直接看官方文档。koa的官方文档很简单,也很详细,不懂的可以先去官网看看。(1)服务端路由(接口)设计服务端路由我们主要使用koa-router,而且使用方法也很简单。代码如下:constKoa=require('koa');constRouter=require('@koa/router');constapp=newKoa();constrouter=newRouter();//获取列表的路由接口router.get('/api/list',(ctx,next)=>{//获取逻辑列表});//路由接口用于上传图片router.post('/api/upload',(ctx,next)=>{//上传图片的逻辑});app.use(router.routes()).使用(路由器。允许的方法());复制代码因为图床的应用非常简单,我们这里直接使用传统的方式来实现。nodeJS的MVC架构可以参考我之前写的node文章。(2)使用glob批量获取图片路径这里主要使用glob通过遍历目录批量获取图片路径。当图像数据量较小时可以使用这种方法。但是一旦图片数量呈指数级增长,建议还是使用数据库来访问。毕竟IO操作是比较划算的。作者为了方便使用了glob。glob是基于node的第三个库,支持我们使用模式匹配遍历文件目录,具体用法如下:importglobfrom'glob'//读取文件router.get('/api/v0/files',ctx=>{constfiles=glob.sync(`${staticPath}/uploads/*`)constresult=files.map(item=>{return`${config.staticPath}${item.split('public')[1]}`})ctx.body={state:200,result}});复制代码实现批量获取图片的api,是不是很简单?我们只需要访问这个接口就可以得到图床上所有图片的列表。当我们访问该接口时,会返回如下数据:3.跨域方案KoaCors的使用介绍,以及如何与前跨域配合。当前页面地址不同,算跨域实现跨域的方式也有很多,比如JSONP跨域、nginx反向代理、服务器端修改header、设置document.domain、使用postMessage技术等,但是目前主流的方式还是基于科尔斯。该服务由不同的域使用。我们需要配置跨域。这里我们使用koa2-cors提供的响应跨域方案。其实原理也很简单。就是配置HTTP请求响应头信息,让我们的服务器支持不同ip访问。它的基本用法如下:importcorsfrom'koa2-cors'//设置跨域app.use(cors({origin:function(ctx){console.log(111,ctx.url)if(ctx.url.indexOf('/api/v0')>-1){return"*";//允许所有域名的请求}return'http://qutanqianduan.com';//这样只允许http://的域名qutanqianduan.comhasbeenrequested},exposeHeaders:['WWW-Authenticate','Server-Authorization'],//获取附加头信息maxAge:5,//该字段可选,用于指定预授权请求的有效期,单位秒credentials:true,allowMethods:['GET','POST','DELETE'],//请求允许的方法allowHeaders:['Content-Type','Authorization','Accept','x-requested-with']//Allowedheaderfieldname}))复制代码通过上面的配置,我们可以实现基本的跨域。如果我们只希望某些特定的接口实现跨域,我们可以设置接口白名单,或者设置域名白名单,只允许特定的域名访问我们的api接口。这种情况更适用于公司内部多个子系统相互协作、通信的场景。4.基于@koa/multer打包文件上传中间件服务器要连接对于客户端上传的文件,我们还需要提供文件上传接口。这里笔者采用koa生态的主流实现方式@koa/multer。具体的使用介绍在官网上也写得很详细。可以到官网学习@koa/multer(1)实现文件上传接口接下来,我们基于它实现文件上传中间件。具体实现如下:importmulterfrom'@koa/multer'import{resolve}from'path'importfsfrom'fs'constrootImages=resolve(__dirname,'../../public/uploads')//上传文件存储路径,以及文件名conststorage=multer.diskStorage({destination:function(req,file,cb){cb(null,rootImages)},filename:function(req,file,cb){let[name,type]=file.originalname.split('.');cb(null,`${name}_${Date.now().toString(16)}.${type}`)}})//文件上传限制constlimits={fields:10,//非文件字段个数fileSize:1024*1024*2,//文件大小单位bfiles:1//文件个数}exportconstcopycode从上面的代码,可以看到我们在destination目录中设置了文件上传的目标目录,通过filename接口设置了上传后的文件名。根据要求配置。其次,结合koa-router实现文件上传接口//lib/upload.js//为了捕获multerexport的错误constuploadSingleCatchError=async(ctx,next)=>{leterr=awaitupload.single('文件')(ctx,next).then(res=>res).catch(err=>err);如果(错误){ctx.status=500ctx.body={state:500,msg:err.message}}}//index.js//上传文件router.post('/api/v0/upload',uploadSingleCatchError,ctx=>{let{文件名,路径,size}=ctx.file;let{source}=ctx.request.body||'unknow';leturl=`${config.staticPath}${path.split('/public')[1]}`ctx.body={state:200,filename,url,source,size}});复制代码,以便我们可以通过任何客户端将图片上传到我们的图像床。(2)删除文件接口实现我们使用原生的nodejs实现删除文件的功能,这里会用到fs模块。具体实现如下://lib/upload.js//删除文件exportconstdelFile=(path)=>{returnnewPromise((resolve,reject)=>{fs.unlink(path,(err)=>{if(err){reject(err)}else{resolve(null)}})})}//删除文件接口router.get('/api/v0/del',asyncctx=>{const{id}=ctx.queryif(id){consterr=awaitdelFile(`${staticPath}/uploads/${id}`)if(!err){ctx.body={state:200,result:'删除成功'}}else{ctx.code=500ctx.body={state:500,result:'文件不存在,删除失败'}}}else500ctx.body={state:500,result:'id不能为空'}}})复制代码如下,我们在自己的客户端应用程序中点击删除按钮,删除图床上的文件。当然,这个图传应用中还有很多接口实现细节,这里就不一一介绍了。有兴趣的朋友可以研究一下。5.使用React开发前端application和xui基本就是用来实现我们的imagebed客户端。客户端的实现和设计风格完全可以自己决定,这里只是介绍一下笔者实现的客户端。我会使用react全家桶,自己开发第三方ui库xui——一个基于react的轻量级UI组件库。关于如何开发自己的组件库,可以参考笔者之前的文章。首先,我们简单开发一个图床应用界面:我们首先引入组件库:importReact,{Component}from'react'import{Notification,message,Layout,Icon}from'@alex_xu/xui'const复制代码并然后构建我们的页面:classUploadPageextendsComponent{state={fileList:[]}componentDidMount(){fetch(apiUrl+'/files').then(res=>res.json()).then(res=>{this.setState({fileList:res.result})})}showAddress=(item)=>{Notification.config({placement:'topRight',})Notification.pop({type:'success',message:'图片地址',duration:10,description:item})}render(){return(XOSS

{this.state.fileList.map((item,i)=>{返回
})}说说前面end--许小希
)}}exportdefaultUploadPage复制代码关于http库,我们可以使用axios、umi-request等任何主流库,这个客户端代码有已发布到github,可以clone到本地运行:基于react+redux+redux-thunk+xui开发的todoOA管理平台,转载请联系前端公众号。