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

使用nodeJs开发自己的图床应用

时间:2023-04-03 11:38:28 Node.js

前言本文主要回顾了作者的nodeJS,通过一个在线的实际案例总结了节点生态的常用技术点和最佳实践。以实战为主输出3个nodeJs项目需要一个月左右。本文为第一篇,主要介绍如何使用nodeJs开发图床应用。该项目对于测试和个人服务网站非常实用,可以在此基础上扩展更强大的应用。本文的图床项目主要是使用Koa开发的。不熟悉的可以先研究一下koa官网,或者看一下作者之前写的nodeJS文章。你将学习Node应用的基本架构和开发NodeJS应用的过程Koa+Koa-Router+glob+Node基础API使用跨域解决方案KoaCors的使用介绍,以及如何基于@进行跨域协作koa/multer打包文件上传中间件使用React开发前端应用,xui基本使用text。首先,图床应用要保证我们的图片资源可以在不同的域下访问。不存在跨域问题,可以支持不同域下的应用上传图片到图床,如下图:结合上图,我们可以先分析一下应用的需求:上面是一个非常简单的影像床应用需求分析,我们将基于此分析构建项目结构并开发我们的应用程序。在开始之前,先看一下简单的实现效果:访问并上传图片,获取图片链接地址,删除图片。这个显示界面只是一个例子。我们可以通过前端的方式设计自己的图床管理界面。这里提供的公共API可以在任意域名下调用,没有跨域问题。前台地址:xui上构建的基于像床接口的前台api开放地址:像床开放地址(免费)1、Node应用的基本架构和NodeJS应用的开发流程。关于nodejs的项目架构以及如何组织nodejs的目录,我在这里30分钟教大家如何优雅的搭建一个nodejs的开发环境和目录设计。本文有详细说明。阅读本文后,您可以学习和研究。开发任何应用程序之前要做的第一件事是了解需求。需求明确后,就可以做技术选型了。开发基于nodeJS的后端应用有很多技术方案。如果熟悉nodejs,可以使用原生nodejs开发应用;对于中小型应用,我们可以直接使用Koa来开发。中间件机制插件化的设计理念可以让我们非常方便的开发自己的中间件;如果涉及到比较复杂的业务线,我们可以使用egg.js或者nest.js作为nodeJS的框架选择,因为本文中的图床应用比较简单,所以作者直接使用koa生态进行开发。接下来看一下我们的图床应用的目录结构:2.koa+Koa-Router+glob+Node使用基础API学习koa最快的方法是直接看官方文档,koa的官方文档是很简单很详细,不懂的可以先看看官网。一、服务端路由(接口)设计服务端路由我们主要使用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()).use(router.allowedMethods());因为图床的应用很简单,我们这里直接用传统的方式实现,nodeJS的MVC架构可以参考我之前写的node文章。2.使用glob批量获取图片路径这里我们主要使用g来批量获取图片路径lob是通过遍历目录得到的。当图像数据量较小时可以使用这种方式,但是一旦图像数据量呈指数级增长,建议使用数据库进行访问。毕竟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的使用介绍,以及如何配合前者跨域因浏览器同源策略,Any发送请求url的协议、域名、端口其中之一与当前页面地址不同的算跨域实现跨域的方式也有很多,比如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//文件个数}exportconstupload=multer({storage,limits})从上面的代码可以看出我们在destination目录下设置了文件上传的目标目录,通过filename接口设置了上传后的文件名。limits是对文件操作的限制,具体可以根据自己的需要配置。其次,结合koa-router实现文件上传接口//lib/upload.js//为了捕获multerexport的错误constuploadSingleCatchError=async(ctx,next)=>{leterr=awaitupload.single('file')(ctx,next).then(res=>res).catch(err=>err);if(err){ctx.status=500ctx.body={state:500,msg:err.message}}}//index.js//上传文件router.post('/api/v0/upload',uploadSingleCatchError,ctx=>{let{filename,path,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:'文件不存在,删除failed'}}}else{ctx.code=500ctx.body={state:500,result:'idcannotbeempty'}}})这样,我们可以通过点击我们的删除按钮来删除图像床客户端应用程序文件。当然,这个图传应用中还有很多接口实现细节,这里就不一一介绍了。有兴趣的朋友可以研究一下。5、使用React开发前端应用和xui的基本使用。接下来我们借用实现我们的形象Bed客户端,客户端的实现和设计风格完全可以自己决定,所以这里只是介绍一下笔者实现的客户端。笔者将使用react全家桶和自己开发的第三方ui库xui——一个轻量级的基于react的组件库,如何开发自己的组件库可以参考笔者之前的文章。首先我们简单开发一个图床应用界面:首先引入组件库:importReact,{Component}from'react'import{Notification,message,Layout,Icon}from'@alex_xu/xui'const{Header,Content,Footer}=Layout连接我们的页面: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)=>{return
})}趣谈前端——许xiaoxi
)}}exportdefaultUploadPage关于http库,我们可以使用axios、umi-request等任何主流库,客户端代码已经发布到github,以及可以clone到本地运行一下:基于react+redux+redux-thunk+xui,我贴出基于react+redux+redux-thunk+开发的todoOA管理平台最终图床的完整代码徐。如果你想了解更多H5游戏、webpack、node、gulp、css3、javascript、NodeJS、canvas数据可视化等前端知识和实战,欢迎在《趣谈前端》学习讨论,探索前端边界在一起