服务端 node app.js
app.js
let express = require("express");
let http = require("http");
var app = express();
let path = require("path");
let bodyParser = require("body-parser");
// 告诉 Express 你将使用EJS模板引擎
app.set("view engine", "ejs");
// 告诉 Express 你的视图存在于一个名为 views 的文件夹中
app.set("views", path.resolve(__dirname, "../views"));
//创建application/json解析
app.use(bodyParser.json());
// 创建 application/x-www-form-urlencoded 编码解析
app.use(bodyParser.urlencoded({ extended: false })); // cdn测试
// var dns = require("dns");
// var options = { all: true };
// dns.lookup("www.qinhuansky.top", options, function(err, address, family) {
// if (err) throw err;
// console.log(address); //[ { address: '122.51.198.35', family: 4 } ]
// });
// dns.resolve4("www.qinhuansky.top", function(err, address) {
// if (err) throw err;
// console.log(JSON.stringify(address)); //["122.51.198.35"]
// });
// cdn测试=================================== // 集群:node实例是单线程作业的。在服务端编程中,通常会创建多个node实例来处理客户端的请求,以此提升系统的吞吐率。对这样多个node实例,我们称之为cluster(集群)。
// var cluster = require("cluster"); //在cluster模块中,主进程称为master,子进程称为worker。
// var cpuNums = require("os").cpus().length; //创建与CPU数目相同的服务端实例
// console.log(cpuNums);
// if (cluster.isMaster) {
// for (var i = 0; i < cpuNums; i++) {
// cluster.fork(); //创建 worker进程
// }
// } else {
// http
// .createServer(function(req, res) {
// res.end(`response from worker ${process.pid}`);
// })
// .listen(3000);
// console.log(`Worker ${process.pid} started`);
// }
// 集群=================================== // 字符编解码:网络通信的过程中,传输的都是二进制的比特位,客户端编码,将需要传送的数据,转成对应的二进制比特位;服务端解码,将二进制比特位,转成原始的数据(字符<->二进制的相互转换)
// var iconv = require("iconv-lite");
// var oriText = "你";
// var encodedBuff = iconv.encode(oriText, "gbk");
// console.log(encodedBuff);
// // <Buffer c4 e3>
// var decodedText = iconv.decode(encodedBuff, "gbk");
// console.log(decodedText); //相同字符集解码
// // 你
// var wrongText = iconv.decode(encodedBuff, "utf8");
// console.log(wrongText);
// // ��
// 字符编解码=================================== // MD5:散列函数(又称哈希算法、摘要算法)主要用来确保消息的完整和一致性。常见的应用场景有密码保护、下载文件校验等
// MD5密码是不可逆的,防止内部存铭文密码。但相同的明文密码,md5值也是相同的。如果事先将常见明文密码的md5值运算好存起来,然后跟网站数据库里存储的密码进行匹配,就能够快速找到用户的明文密码(彩虹表)
// 方案:密码加盐。就是在密码特定位置插入特定字符串后,再对修改后的字符串进行md5运算
// var crypto = require("crypto"); //crypto模块封装了一系列密码学相关的功能,包含md5
// //生成随机盐
// function getRandomSalt() {
// return Math.random()
// .toString()
// .slice(2, 5);
// } // function cryptPwd(password, salt) {
// var saltPassword = password + ":" + salt;
// console.log("原始密码:%s", password);
// console.log("加盐后的密码:%s", saltPassword);
// // 加盐密码的md5值
// var md5 = crypto.createHash("md5");
// var result = md5.update(saltPassword).digest("hex");
// console.log("加盐密码的md5值:%s", result);
// }
// var password = "123456";
// cryptPwd("123456", getRandomSalt());
// 原始密码:123456
// 加盐后的密码:123456:409
// 加盐密码的md5值:69c9c2c61e6e605a43450a643a91543b
// MD5碰撞:相同MD5值,原值不同=================================== // 图片上传
// cnpm i multer --save
var fs = require("fs");
var multer = require("multer");
let qiniu = require("qiniu");
// 空间名
var bucket = "qinhuansky";
// 方式一:默认文件名
// var upload = multer({ dest: "upload/" }); //上传到当前目录的upload下,没有自动创建
// 方式二:自定义文件
var createFolder = function(folder) {
try {
fs.accessSync(folder);
} catch (e) {
fs.mkdirSync(folder);
}
};
var uploadFolder = "./upload/";
createFolder(uploadFolder);
// 通过 filename 属性定制
var storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, uploadFolder); // 保存的路径,备注:需要自己创建
},
filename: function(req, file, cb) {
// 将保存文件名设置为 字段名 + 时间戳,比如 logo-1478521468943
cb(null, file.fieldname + "-" + Date.now());
}
});
// 通过 storage 选项来对 上传行为 进行定制化
var upload = multer({ storage: storage });
// 单图上传;upload.array('logo', 2)表示多图上传
app.post("/upload", upload.single("logo"), function(req, res, next) {
var file = req.file;
console.log("文件类型:%s", file.mimetype);
console.log("原始文件名:%s", file.originalname);
console.log("文件大小:%s", file.size);
console.log("文件保存路径:%s", file.path); //文件保存路径:upload\logo-1577165939230
// 获取存的upload下的二进制文件,转base64
var bData = fs.readFileSync("./upload/logo-1577165939230");
var base64Str = bData.toString("base64");
var datauri = "data:image/png;base64," + base64Str;
console.log(datauri); res.send({ ret_code: "0", data: datauri });
}); app.get("/form", function(req, res, next) {
var form = fs.readFileSync("../middle-view/bodyParser.html", {
encoding: "utf8"
});
res.send(form);
});
// 图片上传=================================== // session相关配置
// npm install --save express-session session-file-store
var session = require("express-session");
var FileStore = require("session-file-store")(session);
var identityKey = "skey";
app.use(
session({
name: identityKey,
secret: "qin", // 用来对session id相关的cookie进行签名
store: new FileStore(), // 本地存储session(文本文件,也可以选择其他store,比如redis的)
saveUninitialized: false, // 是否自动保存未初始化的会话,建议false
resave: false, // 是否每次都重新保存会话,建议false
cookie: {
maxAge: 1800 * 1000 // 有效期,单位是毫秒
}
})
);
// 登录登出---------------------------------------------------- // 登录接口
app.post("/login", function(req, res, next) {
var sess = req.session;
console.log(req.body);
if (req.body.name == "qin" && req.body.password == "123456") {
// 如果用户存在,则通过req.regenerate创建session,保存到本地
req.session.regenerate(function(err) {
if (err) {
return res.json({ ret_code: 2, ret_msg: "登录失败" });
}
req.session.loginUser = req.body.name;
res.json({ ret_code: 0, ret_msg: "登录成功" });
});
} else {
res.json({ ret_code: 1, ret_msg: "账号或密码错误" });
}
}); // 退出登录
app.get("/logout", function(req, res, next) {
// 备注:这里用的 session-file-store 在destroy 方法里,并没有销毁cookie
// 所以客户端的 cookie 还是存在,导致的问题 --> 退出登陆后,服务端检测到cookie
// 然后去查找对应的 session 文件,报错
// session-file-store 本身的bug
req.session.destroy(function(err) {
if (err) {
res.json({ ret_code: 2, ret_msg: "退出登录失败" });
return;
}
// req.session.loginUser = null;
res.clearCookie(identityKey);
res.redirect("/");
});
});
// 检测登录与否
app.get("/", function(req, res, next) {
var sess = req.session;
var loginUser = sess.loginUser;
var isLogined = !!loginUser;
console.log(sess);
res.render("index", {
isLogined: isLogined,
name: loginUser || ""
});
}); // app.use(function(request, response) {
// if (request.url == "/") {
// response.end("Hello qinhuansky");
// } else if (request.url == "/home") {
// response.end("wellcome home");
// } else {
// response.end("404");
// }
// });
http.createServer(app).listen(9527);

客户端,对应上面图片上传和登录登出服务

bodyParser.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<h2>单图上传</h2>
<input type="file" name="logo">
<input type="submit" value="提交">
</form>
</body>
</html>
index.ejs
<!DOCTYPE html>
<html>
<head>
<title>会话管理</title>
</head>
<body>
<h1>会话管理</h1>
<% if(isLogined){ %>
<p>当前登录用户:<%= name %>,<a href="/logout" id="logout">退出登陆</a></p>
<% }else{ %>
<form method="POST" action="/login">
<input type="text" id="name" name="name" value="qin" />
<input type="password" id="password" name="password" value="123456" />
<input type="submit" value="登录" id="login" />
</form>
<% } %> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
$('#login').click(function(evt){
evt.preventDefault();
$.ajax({
url: '/login',
type: 'POST',
data: {
name: $('#name').val(),
password: $('#password').val()
},
success: function(data){
if(data.ret_code === 0){
location.reload();
}
}
});
});
</script>
</body>
</html>

以上三文件目录(纯记录学习,目录比较乱^0^)

以上学习代码参考: https://github.com/chyingp/nodejs-learning-guide/blob/master/README.md

web框架express学习一的更多相关文章

  1. gogin web框架部署学习

    首先去git上面找了一个gin框架拿来学习gin web开发: flipped-aurora/gin-vue-admin: 基于vite+vue3+gin搭建的开发基础平台(已完成setup语法糖版本 ...

  2. golang web框架 beego 学习 (一) 环境搭建

    下面的命令我都是在$GOPATH的路径下执行的: 1. 首先下载beego框架: go get github.com/astaxie/beego (注意:运行上面命令时没有反应,需要在etc/host ...

  3. 基于node.js的web框架express

    1.安装node.js方法: window :https://nodejs.org/en/ linux:http://www.runoob.com/nodejs/nodejs-install-setu ...

  4. golang web框架 beego 学习 (四) 连接mysql

    1 DB参数配置在app.conf appname = gowebProject httpport = runmode = dev [db] host= localhost port= databas ...

  5. golang web框架 beego 学习 (三) beego获取参数

    直接上常用的例子吧: A:     获取URL中的参数 router func init() { beego.Router("/task/?:id/?:name", &co ...

  6. golang web框架 beego 学习 (二) router and controller

    1 Router和Controller的常用配置 beego.Router("/user/admin", &controllers.UserController{}) // ...

  7. golang web框架 beego 学习 (七)json转数组

    Modules type User struct { Id int64 `json:"id"` Name string `json:"name"` Email ...

  8. golang web框架 beego 学习 (六) request body和module的映射

    router.go package routers import ( "gowebProject/controllers" "github.com/astaxie/bee ...

  9. golang web框架 beego 学习 (五) 配置文件

    app.conf: appname = gowebProject httpport = runmode = dev copyrequestbody = true [db] host= localhos ...

随机推荐

  1. springboot 2.x相关配置

    1.在配置文件中进行配置 #############指定项目中所有的日期类型返回json格式########### spring.jackson.date-format=yyyy-MM-dd HH:m ...

  2. JavaScript仿淘宝实现放大镜效果的实例

    我们都知道放大镜效果一般都是用于一些商城中的,列如每当我们打开淘宝,天猫等pc端时,看到心仪的物品时,点击图片时,便呈现出放大镜的效果.在没有去理解分析它的原理时,感觉非常的神奇,当真正地去接触,也是 ...

  3. vue video全屏播放

    需求: 1.视频为长方形,页面初始化打开为横屏全屏播放视频. 2.微信不支持自动播放,故自动播放需求删除. 方法: 1.vue-video-player插件 因需求较简单,仅要求播放本地一个视频,故未 ...

  4. ATM&购物商城程序

    模拟实现一个ATM + 购物商城程序 额度15000或自定义 实现购物商城,买东西加入购物车,调用信用卡接口转账 可以体现,手续费5% 支持多账户登录 支持账户间转账 记录每月日常消费流水 提供还款接 ...

  5. OC学习篇之---单例模式

    在之前的一片文章中介绍了对象的拷贝相关知识:http://blog.csdn.net/jiangwei0910410003/article/details/41926531,今天我们来看一下OC中的单 ...

  6. Python基础教程(005)--为什么要学习Python?

    前言 为什么要选择Python学习 知识点 因为Python代码量少. 同样一个问题,用不同的语言,代码量差距还是很大的.一半情况下,Python是java的1比5,所以说,人生苦短,我用Python ...

  7. 【Java架构:基础技术】一篇文章搞掂:MyBatis-Plus

    前言 Mybatis:一个流行的半自动ORM框架. Mybatis-Plus:一个Mybatis的增强工具,在Mybatis的基础上只做增强不做改变,为简化开发.提高效率而生. 本文使用的版本:myb ...

  8. HDU 1724 Ellipse (自适应辛普森积分)

    题目链接:HDU 1724 Problem Description Math is important!! Many students failed in 2+2's mathematical tes ...

  9. Rust <0>:源代码组织,Cargo 入门

    Rust 源代码组织,使用配套的 Cargo 工具,其功能强大,程序员可摆脱 C/C++ 中需要自行维护 make.cmake 之类配置的工作量. 初始化一个项目: cargo new --bin h ...

  10. PAT甲级——A1144 TheMissingNumber【20】

    Given N integers, you are supposed to find the smallest positive integer that is NOT in the given li ...