本话概要
【绝对干货】🔥
本篇博文主要介绍文件共享平台的后端如何搭建。从几个方面入手:路由怎么配置?静态文件路径如何设置?session的用途及配置?跨域问题如何解决?
通过本文,你可以基本了解整个后端的搭建流程及关键步骤。我建议你和我一步步操作,真正实现后端架构搭建。
当然,本文仅仅是后端教程的开端,其他教程将在后续更新。👇
Koa介绍
Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。官网
你可以把koa看作express的替代品,koa的一些语法糖使得后端搭建更加简单,且丰富的node库资源,很多功能的中间件都已被封装好,例如koa-static、koa2-cors、koa-body等。下面我们就进入实战,教大家如何搭建后端。
从一个app.js开始
首先,创建一个项目文件夹,命名为shareFile_server。
在该文件夹下初始化node项目
npm init
然后我们就得到一个基本的node项目结构。
接下来,我们创建一个app.js文件,作为服务器的运行代码。
安装包
首先将需要的node包一次性安装好,安装方法如下:
npm install koa koa-body koa-router koa-session koa-static koa2-cors --save-dev
如果你觉得一次性都下载,有中途报错的风险,你也可以一个一个安装。如果觉得下载太慢,也可以用淘宝镜像安装方法,安装方法如下:
npm --registry https://registry.npm.taobao.org install 包名 --save-dev
所有包安装好后,我们进入coding环节。
允许多文件上传
文件共享平台自然需要服务端允许文件上传,这里设置多文件上传。配置很简单,引入koa-body。
// app.js
app.use(koaBody({
multipart: true, // 支持多文件上传
formidable: {
maxFieldsSize: 5 * 1024 * 1024, // 最大文件为5兆
multipart: true // 是否支持 multipart-formdate 的表单
}
})
);
配置路由
首先,服务端需要解决路由问题。简单来说,路由就是根据不同的访问路径,返回不同的资源文件或者不同的结果字段。比如,你访问一个静态资源(图片、文件),服务器应该返回静态资源本身;如果你想查询数据库,服务器应该返回查询后的结果,以json的形式返回给浏览器。这就是路由的作用。路由使得服务端的功能很容易得到扩展,而不是单一的功能。
利用koa配置路由写法非常优美。首先我们在app.js头部引入koa包并创建示例:
const Koa = require('koa');
const app = new Koa();
为了使得路由功能更加集中,我将路由部分提到单独的文件中。首先在根目录创建一个router的文件夹,然后在文件夹内创建一个index.js,作为路由的配置文件。
然后,在router文件夹下继续创建几个不同的路由模块:user.js、file.js、directory.js…这个依照不同的功能可以设置不同的路由。每一个路由模块对应了一个根路径。
接下来,在index.js中配置路由,写法如下:
// router/index.js
const router = require('koa-router')();
const directory = require('./directory');//处理文件夹
const file = require('./file');//处理文件
const user = require('./user');//处理用户
router.use('/directory',directory.routes(),directory.allowedMethods());
router.use('/file',file.routes(),file.allowedMethods());
router.use('/user',user.routes(),user.allowedMethods());
module.exports = router;
此时,你的项目文件夹结构应该是:
- shareFile_server/
- node_modules/
- router/
- index.js
- file.js
- user.js
- directory.js
- app.js
- package.json
- package-lock.json
接下来我们回到app.js文件中,引用该路由配置。
const router = require('./router/index');
// 加载路由中间件
app.use(router.routes(), router.allowedMethods());
另外,我们先把file.js、user.js和directory.js中写如下代码,保证程序可以正常运行:
// file.js、user.js、directory.js
const router = require('koa-router')();
//...待补充
module.exports = router;
这样,整体的路由配置流程我们就过了一遍。具体的路由怎么写,我将在后面的教程详述。不急~
设置静态文件路径
设置静态文件路径的原因,是我们这个文件共享平台本身的属性决定的。因为有一些文件是需要通过访问地址可以直接访问到的,例如图片,所以服务端需要把这些文件直接返回给浏览器,而如果用传统的办法,我们需要队每个请求都做一个判断,根据不同的文件类型,设置不同的content-type,以便浏览器识别出返回的文件类型,进行不同的响应。
另外,如果前端的代码也打包放到后台,我们就更需要设置静态文件路径了,否则就会出现404(Not Found)的问题。当然,本系列教程的前后端代码并没有统一放在后端,后端的静态文件单纯指文件存储的文件夹。
现在通过koa-static包,我们可以直接配置静态文件的路径,省去很多烦恼。
首先,我们在根目录创建一个static文件夹,作为静态资源文件目录。
然后,我们在app.js中写如下代码:
const serve = require('koa-static');
app.use(serve(path.join(__dirname,'static')));
这样,我们就设置好了静态文件路径。需要注意的是,设置了静态文件路径后,通过浏览器访问该资源,不要出现static这个路径,而是直接访问static内的文件,因为默认是以static作为根目录的。比如,端口是8000,我们要访问static/img/example.png,需要按照如下链接访问:
http://localhost:8000/img/example.png
设置session
首先解释下为什么需要设置session。
session是浏览器访问服务器,会在服务器端的内存里开辟一块内存,每个session都有属于自己的sessionid,用来区分不同客户。
准确来说,这个平台用session具体是要解决:用户是否在线的问题
。
如果用户未登录,需要跳转到登录页,如果已登录,就可以正常得到服务。
如何判断用户是否在线,常用的解决方案有两套:token和session鉴权。
token的原理是用户第一次访问服务器,服务器根据用户的唯一标识(如userid),用一些加密算法(如HMAC-SHA256),通过一个密匙,生成一个令牌(token),然后用Base64编码后发送给用户。用户将这个token保存起来,以后每次请求都带上这个token,服务端收到后用密匙验证token,来判断用户是否已登录。
Session鉴权的原理如图所示(忘记在哪里截图的了,不是自己画的)。用户登录后,服务器会向用户发放session ID,存在用户浏览器的cookie中,这个cookie用户在前端是无法修改的,当用户发送请求,请求头需要带上session ID这个cookie。服务器维护一个session表,通过设置一定的时长,来管理每个用户的登录状态,超时会将该用户的session删除,这样当用户从前端发来请求,后端的session表中不存在该session ID,就会提示用户重新登录。
为了实现session,我们在app.js中引用koa-session包:
const session = require('koa-session');
app.keys = ['never mind, just test'];
//设置session
app.use(session({
key: 'koa:sess', /** cookie的名称,可以不管 */
maxAge: 7200000, /** cookie的过期时间(毫秒),这里表示2个小时(2*60*60*1000) */
overwrite: true, /** (boolean) can overwrite or not (default true) */
httpOnly: true, /** (boolean) httpOnly or not (default true) */
signed: true, /** (boolean) signed or not (default true) 是否加密,如果加密,需要给上面的app.keys赋值*/
rolling: false, /** (boolean) Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown. (default is false) */
renew: false, /** (boolean) renew session when session is nearly expired, so we can always keep user logged in. (default is false)*/
},app));
这样就完成了session的配置,我们在后续登录鉴权的教程具体教大家怎么用session,很简单。
解决跨域问题
跨域问题是前后端交互经常遇到的问题。后端要解决跨域问题,需要进行配置,这里用koa2-cors解决跨域问题:
// app.js
const cors = require('koa2-cors');
//设置跨域参数
app.use(cors({
origin: function(ctx) { //设置允许来自指定域名请求
const whiteList = []; //可跨域白名单,这里设置前端的
let url = ctx.header.origin;
if(whiteList.includes(url)){
return url
}
return 'http://localhost:3000' //默认允许本地请求3000端口可跨域
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
maxAge: 5,
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE','PUT'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
})
)
按照上述代码,我们解决了跨域问题。
最后我们需要把服务运行起来,设置服务端口为3000
app.listen(3000, () => {
console.log('server is listen in 3000');
});
完整代码
// app.js完整代码
const Koa = require('koa');
const path = require('path');
const router = require('./router/index');
const koaBody = require('koa-body');
const serve = require('koa-static');
const cors = require('koa2-cors');
const session = require('koa-session');
const app = new Koa();
// 设置session
app.keys = ['never mind, just test'];
//设置session
app.use(session({
key: 'koa:sess',
maxAge: 7200000,
overwrite: true,
httpOnly: true,
signed: true,
rolling: false,
renew: false,
},app));
//设置跨域参数
app.use(cors({
origin: function(ctx) { //设置允许来自指定域名请求
const whiteList = []; //可跨域白名单
// let url = ctx.header.referer.substr(0,ctx.header.referer.length - 1);
let url = ctx.header.origin;
if(whiteList.includes(url)){
return url
}
return 'http://localhost:3000' //默认允许本地请求3000端口可跨域
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
maxAge: 5,
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE','PUT'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
})
)
//多文件上传
app.use(koaBody({
multipart: true,
formidable: {
maxFieldsSize: 5 * 1024 * 1024, // 最大文件为5兆
multipart: true
}
})
);
// 设置静态文件路径
app.use(serve(path.join(__dirname,'static')));
// 加载路由中间件
app.use(router.routes(), router.allowedMethods());
app.listen(3000, () => {
console.log('server is listen in 3000');
});
我们运行app.js
node app.js
如果没有报错,说明基本架构没问题~大功告成👌你学会了吗?
下期预告
下一话,我将教大家后台如何与mongodb交互,并封装CURD操作,提高通用性。怀挺💪
下期再见👋