NodeJS七天课程学习笔记_第7天综合案例

课程内容概要:

1.  介绍path模块的api

2. 重点介绍path.join方法 与 __dirname

3. 介绍xheditor编辑器的使用(包括上传图片)

4. 介绍formidable中间件处理上传的图片

提了一下 编辑器默认的是: 15号字体 因为大小最合适
讲了一下chrome的插件: editthiscookie
不要担心模块重复加载性能问题,因为模块加载是有缓存的

中间件midware 就是一个方法(包装)

提了一下,使用 postman 模拟请求

提了一下 chrome插件: cors toggle

喊了一下口号: 热爱编程,享受生活

推荐了「深入理解ES6」(尼古拉斯·泽卡斯)、「JavaScript高级程序设计」(小孩望远镜)、

总结了MongoDB数据库的特点:
    1. 灵活
    2. 不用建表
    3. 业务的改动不用关心表结构
    4. DBA、架构师 都要掌握(设计、维护、分布式计算)

总结了Mongoose的使用方法:
    1. 虽然mongodb官方包也可以操作MongoDB数据库,但是...
    2. mongoose开发者是 WordPress团队
    3. 设计Schema
    4. 生成Model(模型构造函数)
    5. CRUD (支持Promise.then语法)

总结了Promise的使用方法:
    1. 介绍了什么是回调地狱(回调函数中层层嵌套回调函数)
    2. ECMAScript6 中新增了一个API: Promise
    3. Promise相当于一个容器(同步执行),一旦创建会立即执行里面的代码(通常是异步操作的代码块block)
    4. 异步任务 初始状态是pending
    5. 最终状态只能是成功(resolve)或者失败(reject)
    6. then方法的参数1是成功的结果(resolveCallback)
    7. then方法的参数2是失败的结果(rejectCallback)
    8. 可以在then方法中返回另一个promise对象,这样就可链式调用then方法

在Node的命令行中,介绍了一下path模块的常用API

如图所示:

介绍一下path路径操作模块
1. path.basename 获取带扩展名的 文件名,如index.html
2. path.dirname  获取目录部分,如"/Users/beyond/sg_node"
3. path.extname  获取扩展名部分,如".html"
4. 强大的path.parse方法,将一个路径转成对象
   例如: /Users/beyond/sg_node/index.html
   root: "/" 表示 根目录
   name: "index" 表示不带后缀的文件名
   ext: ".html" 表示后缀名(带点号)
   base: "index.html" 表示带后缀的文件名
   dir: "/Users/beyond/sg_node" 表示 目录部分
5. 强大的path.join方法
   进行多个路径拼接(能智能处理多写或少写 / )

6. path.isAbsolute 判断一个路径是不是绝对路径

7. 强大path.resolve方法,如下图所示

重点来了!
Node中引入自定义模块时的路径标识符就只是相对于当前文件的路径,
与 将来node命令执行时 命令行所在的路径无关!!!
例如:
require('./router')
require('./dao')
这个自定义模块的路径,就只是相对于当前的文件的路径而言的
与 将来node命令执行时 命令行所在的路径无关!!!

区别,注意:
fs.readFile('a.txt')
在readFile读取文件时,这个相对路径,相对的可是将来 Node命令执行时 命令行所在的路径喔~~~
因此,在读写文件时,使用相对路径是不安全的,
因为Node设计为: 读写文件的相对路径只是相对于 Node命令执行时,命令行所在的路径

因此,为了把文件读取时,这个相对路径,转成绝对路径,
我们隆重介绍Node中除了require和exports之外的另外两个非常重要的成员:
__dirname 它可动态获取当前模块所处目录的绝对路径
__filename 它可动态获取当前模块的绝对路径

特别注意: 
__dirname和__filename 与 将来node执行时 命令行所在的路径 无关的

当然在把相对路径转换成绝对路径的时候,为了避免手动拼接路径出错,我们推荐使用path.join方法喔~

在开始blog综合案例之前,先讲了一下如何使用path.join(__dirname,'public')生成绝对路径,

以保证任何情况下,目录都是正确路径

node_48的目录情况如下:

示意图就是这样的:

node_48_1.js代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};}  // 演示readFile中相对路径 是相对于 node命令执行时,命令行所处的路径
require('./subfolder/node_48_2.js')

node_48_2.js代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};}  // 演示readFile中相对路径 是相对于 node命令执行时,命令行所在的路径
fs = require('fs')
// readFile相对路径 不安全, 因为它是相对于 node命令执行时,命令行所在路径
fs.readFile('./node_48_3.txt',function (error,data) {if (error) {NSLog('读取失败: ' + error)}else{NSLog('读取成功: \n' + data)}})

我们先来 正确执行一次 ,即:

1. 将命令行 cd 到subfolder目录中

2. node命令 执行 上一级目录中的node_48_1.js文件

效果如下:

下面,我们直接在node_48目录下执行该目录下的node_48_1.js

由于 node_48_1.js中require进来了子目录subfolder中的node_48_2.js

而node_48_2.js使用相对路径读取的是同级目录subfolder中的node_48_3.txt

但是: readFile中相对路径设计之初就 是 相对于 执行Node命令时,所处路径

而我们这时, 是在node_48目录下 执行的node命令, 而不是 subfolder目录了

因此,报错: 在node_48目录中找不到node_48_3.txt,如图所示:

解决办法如下:

使用Node提供的__dirname和path.join方法 把readFile中的相对路径,改成绝对路径就好了

node_48_2.js代码如下

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};}  // 演示readFile中相对路径 是相对于 node命令执行时,命令行所在的路径
fs = require('fs')
path = require('path')
// readFile相对路径 不安全, 因为它是相对于 node命令执行时,命令行所在路径
// fs.readFile('./node_48_3.txt',function (error,data) {// 通过 Node提供的__dirname和path.join,将相对路径转成绝对路径
fs.readFile(path.join(__dirname,'./node_48_3.txt'),function (error,data) {if (error) {NSLog('读取失败: ' + error)}else{NSLog('读取成功: \n' + data)}})

这时,无论你在哪个路径下通过node 命令执行 node_48_1.js都能成功读取node_48_3.txt的内容了

效果如下:

下面的node_49.js 简单演示了一下node提供的__dirname和__filename输出结果:

node_49.js代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};}  NSLog(__dirname,false)
NSLog(__filename)

(注意: __dirname和__filename  千万不要使用 字符串拼接)

效果如下:

在开始blog正式项目之前,我们还要先讲一下

如何  用使用富文本编辑器xheditor来上传文件

以及 如何使用中间件formidable 处理上传的头像图片

总体效果如下:

先说说xheditor的使用方法

官网:xheditor.com

第1步, 下载(我这儿下载的是1.4M大小的V1.2.2版本)

第2步, 解压

第3步, 拷贝 3个文件夹, 3个js文件 到public/js目录下

表情目录: xheditor_emot

皮肤目录: xheditor_skin

插件目录: xheditor_plugins

jquery文件: jquery1.4.4.js

语言包文件: xheditor-zh-cn.js

核心JS文件: xheditor-1.2.2.min.js

如下图所示

第4步,使用xheditor

这儿我们使用的是node_50_edit.html作为上传页面

步骤1:  严格按顺序 引入public/js目录下的 xheditor 相关的3个js文件

        <!-- 第1步. 必须先引入 jquery 1.4.4 --><script type="text/javascript" src="public/js/jquery1.4.4.js"></script><!-- 第2步. xheditor的核心JS --><script type="text/javascript" src="public/js/xheditor-1.2.2.min.js"></script><!-- 第3步.  xheditor 支持中文 --><script type="text/javascript" src="public/js/xheditor-zh-cn.js"></script>

步骤2: 创建表单,里面有一个textarea, id为 id_xheditor (后面要用这个id查找并初始化)

        <div style="margin:0 auto;text-align:center;padding-left:50px;padding-right:50px;"><form method="post" action="xxx.php"><!-- 第4步. xheditor所使用的id --><textarea id="id_xheditor" rows="12" cols="80" style="width: 100%;height:240%;">未闻花名 vwhm.net</textarea></form></div>

步骤3: 在document.ready方法中, 根据textarea的id_xheditor查找,并进行初始化

            $(document).ready(function () {var uploadUrl = "uploadfile"// 第5步. 图片上传配置$('#id_xheditor').xheditor({// 上传图片upImgUrl: uploadUrl,// 支持的图片后缀upImgExt: "jpg,jpeg,gif,png",// 上传回调函数onUpload: uploadCompleteFunction,// 多文件上传upMultiple: true,// 默认皮肤skin: 'default',// 工具栏样式tools: 'full',upLinkUrl:uploadUrl,upLinkExt:"zip,rar,txt",upFlashUrl:uploadUrl,upFlashExt:"swf",upMediaUrl:uploadUrl,upMediaExt:"avi,mp4,wmv,flv"})})

步骤4: 做做样子,实现一下 上传回调函数(初始化的时候不写回调,那就不实现 也不影响)

            // 第6步. 上传回调函数,参数是服务器返回的 图片url(例如:upload/beyond.jpg)function uploadCompleteFunction (responseMsg) {NSLog('上传回调: ' + responseMsg)}

完整的node_50_edit.html代码如下:

<!DOCTPYE html>
<html lang="zh">
<head>  <link rel="icon" href="public/img/beyond.jpg" type="image/x-icon"/><meta charset="UTF-8"><meta name="author" content="beyond"><meta http-equiv="refresh" content="520"><meta name="description" content="未闻花名-免费零基础教程-beyond"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0" /><meta name="keywords" content="HTML,CSS,JAVASCRIPT,JQUERY,XML,JSON,C,C++,C#,OC,PHP,JAVA,JSP,PYTHON,RUBY,PERL,LUA,SQL,LINUX,SHELL,汇编,日语,英语,泰语,韩语,俄语,粤语,阿语,魔方,乐理,动漫,PR,PS,AI,AE"><title>beyond心中の动漫神作</title><link rel="stylesheet" type="text/css" href="public/css/beyondbasestylewhite5.css"><script type="text/javascript" src="public/js/nslog.js"></script><!--[if lt IE 9]><script src="//apps.bdimg.com/libs/html5shiv/3.7/html5shiv.min.js"></script><script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.js"></script><![endif]--><style type="text/css">body{font-size: 100%; /*声明margin和padding是个好习惯*/  margin: 0;  padding: 0; background-image: url("public/img/sakura4.png");  background-repeat: no-repeat;  background-position: center center;  }</style><!-- 绿色按钮的css效果 --><link rel="stylesheet" type="text/css" href="public/css/beyondbuttongreen.css"><!-- 第1步. 必须先引入 jquery 1.4.4 --><script type="text/javascript" src="public/js/jquery1.4.4.js"></script><!-- 第2步. xheditor的核心JS --><script type="text/javascript" src="public/js/xheditor-1.2.2.min.js"></script><!-- 第3步.  xheditor 支持中文 --><script type="text/javascript" src="public/js/xheditor-zh-cn.js"></script></head>  <body>  <h1 style="color:white;text-shadow:2px 2px 4px #000;letter-spacing:5px;" class="sgcontentcolor sgcenter">  未闻花名</h1><div style="margin:0 auto;text-align:center;padding-left:50px;padding-right:50px;"><form method="post" action="xxx.php"><!-- 第4步. xheditor所使用的id --><textarea id="id_xheditor" rows="12" cols="80" style="width: 100%;height:240%;">未闻花名 vwhm.net</textarea></form></div><p class="sgcenter"><b>注意: </b>NodeJS + formidable中间件 + xheditor编辑器</p><footer id="copyright"><p style="font-size:14px;text-align:center;font-style:italic;">  Copyright © <a id="author">2018</a> Powered by <a id="author">beyond</a>  </p>        </footer><script type="text/javascript">/*
重要说明:
1,上传文件域的名字 必须为:filedata
2,返回结构必需为json,并且结构必须如下:
完整的图片url是 http://localhost:5267/upload/beyond.jpg
{"err":"","msg":"upload/beyond.jpg"}
若上传出现错误,请将错误内容保存在err变量中;
若上传成功,请将服务器上的绝对或者相对地址保存在msg变量中。
编辑器若发现返回的err变量不为空,则会弹出窗口显示返回的错误内容
*/$(document).ready(function () {var uploadUrl = "uploadfile"// 第5步. 图片上传配置$('#id_xheditor').xheditor({// 上传图片upImgUrl: uploadUrl,// 支持的图片后缀upImgExt: "jpg,jpeg,gif,png",// 上传回调函数onUpload: uploadCompleteFunction,// 多文件上传upMultiple: true,// 默认皮肤skin: 'default',// 工具栏样式tools: 'full',upLinkUrl:uploadUrl,upLinkExt:"zip,rar,txt",upFlashUrl:uploadUrl,upFlashExt:"swf",upMediaUrl:uploadUrl,upMediaExt:"avi,mp4,wmv,flv"})})// 第6步. 上传回调函数 (初始化的时候不写回调,那就不实现 也不影响) // 参数是服务器返回的 图片url(例如:upload/beyond.jpg)function uploadCompleteFunction (responseMsg) {NSLog('上传回调: ' + responseMsg)}</script>
</body>
</html>  

说完了xheditor的使用方法,接下来说说如何使用用来处理上传文件的 中间件 formidable

官网的使用文档: npmjs.com/package/formidable#readme

其他的几个也可以实现表单中上传文件的解析

第1步, 安装formidable:

npm install formidable --save

第2步, 配置

// ---------------使用formidable解析上传的图片--------------------
var formidable = require('formidable')
// var util = require('util')  // 只是调试用
var path = require('path')

第3步, 使用

重要说明:

重要说明:
1,上传文件域的名字 必须为:filedata

2,返回结构必需为json,并且结构必须如下:

// 完整的图片url是 http://localhost:5267/upload/beyond.jpg

{"err":"","msg":"upload/beyond.jpg"}
若上传出现错误,请将错误内容保存在err变量中;
若上传成功,请将服务器上的绝对或者相对地址保存在msg变量中。
编辑器若发现返回的err变量不为空,则会弹出窗口显示返回的错误内容

// ----------------上传一张图片-------------------
router.post('/uploadfile',function (request,response) {// 使用formidable中间件var form = new formidable.IncomingForm();// 配置 上传保存路径 (应该将日期计算进来)form.uploadDir = '/Users/beyond/sg_node/node_27/uploads'// 让formidable中间件 解析上传的图片form.parse(request,function (error,fields,files) {// var uploadObj = util.inspect({//     fields: fields,//   files: files// })// 保存的完整路径var uploadSavePath = files['file']['path']var pathObj = path.parse(uploadSavePath)// 文件名,不带后缀var filePlainName = pathObj.name// 回写给xheditor用的成功的json,格式必须这样写// {"err":"","msg":"uploads/beyond.jpg"}var jsonObj = {err: "",msg: 'uploads/' + filePlainName}// 回写给浏览器response.writeHead(200, {'content-type': 'text/json'});response.end(JSON.stringify(jsonObj));})
})

node_50_index.js这个APP入口文件完整的代码如下:

function NSLog(loli,needLogo=true) {console.log(loli);if(needLogo){console.log('\nCopyright © 2018 Powered by beyond')};}  // 导入框架
var express = require('express')
var path = require('path')
// 创建服务器对象
var appServer = express()
// 监听端口,并启动服务
appServer.listen(5267,function (error) {if (error) {return NSLog('启动失败: ' + error)}NSLog('服务启动成功')
})
// -----------------------------------// 静态资源请求时的 staticFileUrlPrefix
var staticFileUrlPrefix = '/public/'
// var staticFileUrlPrefix = '/public' // 访问也只能使用 localhost:5267/public/img/beyond.jpg
// 磁盘上的静态资源目录
var staticFilePath = './public/'
// var staticFilePath = 'public' var callbackFunction = express.static(staticFilePath)
appServer.use(staticFileUrlPrefix,callbackFunction)
// 再开一个静态资源目录
appServer.use('/uploads/',express.static(path.join(__dirname,'uploads')))// -----------------------------------// 指明:对于 所有后缀为html 的模板文件 使用模板引擎
var templateFileSuffix = 'html'
appServer.engine(templateFileSuffix,require('express-art-template'))
// 下面这一句参数配置,可有可无
appServer.set('view options',{debug: process.env.NODE_ENV !== 'production'
})
// 注意:如果不想把模板文件放在默认的views目录下,则可以通过下面代码更改设置
// appServer.set('views','其他目录')// -----------------------------------
// 使用middleware中间件body-parser进行post请求体中数据解析
var bodyParser = require('body-parser')
// 设置解析 application/x-www-form-urlencoded
appServer.use(bodyParser.urlencoded({extended: false}))
// 设置解析 application/json
appServer.use(bodyParser.json())// -----------------------------------
// 自定义路由设计的目的是:
// 1.让主入口程序的职责更加单一,代码更加简洁
//     1.1 创建服务
//     1.2 做一些服务相关的配置,比如:
//           1.2.1 静态资源配置
//           1.2.2 模板引擎配置
//           1.2.3 body-parse 解析表单
//           1.2.4 挂载自定义路由
//           1.2.5 监听端口,启动服务
// 使用自定义的路由模块 必须使用./
// 注意: 配置模板引擎和body-parser, 一定要在挂载路由之前
var beyondRouter = require('./node_50_router')
appServer.use(beyondRouter)

node_50_router.js这个路由文件完整的代码如下:

function NSLog(loli) {console.log(loli);return 'Copyright © 2018 Powered by beyond';};
/*自定义路由模块的职责是:专门处理所有的路由根据不同的请求方式和路径,采取相应的处理方法
*/
// express 专门提供了路由的处理方法
var express = require('express')// ---------------使用formidable解析上传的图片--------------------
var formidable = require('formidable')
// var util = require('util')
var path = require('path')
// -----------------------------------// 1.使用express专门提供的路由器处理路由
var router = express.Router()// -----------------------------------
// 时间格式化
// var BeyondDateFormatFunction = require('./BeyondDateFormat')// ----------------首页-------------------
router.get('/',function (request,response) {response.render('index/node_50_edit.html')
})// ----------------上传一张图片-------------------
router.post('/uploadfile',function (request,response) {// 使用formidable中间件var form = new formidable.IncomingForm();// 配置 上传保存路径 (应该将日期计算进来)form.uploadDir = '/Users/beyond/sg_node/node_27/uploads'// 让formidable中间件 解析上传的图片form.parse(request,function (error,fields,files) {// var uploadObj = util.inspect({//     fields: fields,//   files: files// })// 保存的完整路径var uploadSavePath = files['file']['path']var pathObj = path.parse(uploadSavePath)// 文件名,不带后缀var filePlainName = pathObj.name// 回写给xheditor用的成功的json,格式必须这样写// {"err":"","msg":"uploads/beyond.jpg"}var jsonObj = {err: "",msg: 'uploads/' + filePlainName}// 回写给浏览器response.writeHead(200, {'content-type': 'text/json'});response.end(JSON.stringify(jsonObj));})
})
// 3.在模块文件最后,导出router
module.exports = router

整个NodeJS + formidable中间件 + xheditor上传图片的效果如下:

明天开始正式的blog综合项目

未完待续,下一章节,つづく

NodeJS_07_path模块_xheditor编辑器_formidable中间件相关推荐

  1. csrf跨站请求伪造,CBV添加装饰器,auth认证模块,基于django中间件设计项目功能

    文章目录 csrf跨站请求伪造 csrf的定义 csrf的分类 csrf的攻击过程 csrf的攻击条件 举例说明 Django提供的解决策略 csrf相关装饰器 FBV CBV 方法一(直接在类中的某 ...

  2. node.js 中间件_Node.js中的Passport中间件(模块)

    node.js 中间件 Hi! Welcome to Node.js Authentication Series, where we'll study and program the passport ...

  3. 能带曲线图绘制python_如何使用python的matplotlib模块画折线图

    python是个很有趣的语言,可以在cmd命令窗口运行,还有很多的功能强大的模块.这篇经验告诉你,如何利用python的matplotlib模块画图. 工具/原料 windows系统电脑一台 pyth ...

  4. ios业务模块间互相跳转的解耦方案

    *此文章需有一点runtime的知识,假设你不了解runtime,<高速理解Runtime of Objective-C>: http://mp.weixin.qq.com/s?__biz ...

  5. h5页面保存img_如何设计H5编辑器中的模版库并实现自动生成封面图

    往期精选 H5编辑器的图片上传和图片库设计方案 如何实现H5编辑器的实时预览和真机扫码预览功能 在线IDE开发入门之从零实现一个在线代码编辑器 基于React+Koa实现一个h5页面可视化编辑器-Do ...

  6. c #include如何找到文件_使用 MATLAB Function 模块集成 C 代码

    检索   使用 MATLAB Function 模块集成 C 代码 从 Simulink 模型中调用 C 代码 您可以使用 MATLAB Function 模块从 Simulink® 模型中调用外部 ...

  7. 如何设计H5编辑器中的模版库并实现自动生成封面图

    往期精选 H5编辑器的图片上传和图片库设计方案 如何实现H5编辑器的实时预览和真机扫码预览功能 在线IDE开发入门之从零实现一个在线代码编辑器 基于React+Koa实现一个h5页面可视化编辑器-Do ...

  8. 市面上主流编辑器介绍(2021/05/20)

    市面上主流编辑器介绍(2021/05/20) 背景 Markdown是一种有用的轻量级标记语言,后续Markdown简写为md. 富文本编辑器(Rich Text Editor,RTE)是一种可内嵌于 ...

  9. 通俗易懂的讲讲什么是中间件?

    学习视频:[学相伴]RabbitMQ最新完整教程IDEA版通俗易懂 | KuangStudy | 狂神说 | 学相伴飞哥_哔哩哔哩_bilibili 目录 一.中间件简介 1.1.什么是中间件 1.2 ...

最新文章

  1. raid模式_基于网络的磁盘热备技术|网络RAID-1
  2. MATLAB实现最优低通滤波器的函数
  3. 为什么可能导致睡眠的函数都不能在中断上下文中使用呢?【转】
  4. c语言switch写值班表,如何用asp编写按周轮换的值班表?例,1月份的值班领导有4位,怎样写可以让4位领导的名字自动到时间显示...
  5. Effective Java 学习笔记 1
  6. 7.python xmlrpclib及allownone作用
  7. 自定义ClassLoader
  8. 前端 JS 之 AJAX 简介及使用
  9. JAVA8——StringJoiner类
  10. C++中strftime()的详细说明
  11. css实现圆球旋像水波波动_66 个超有用的CSS 特效!
  12. sha256算法细节详解
  13. PD快充3.0协议芯片
  14. 《中国医学大成》目录
  15. android+锁屏录像,快速录像机(锁屏录像)
  16. 2020 ACM杰出科学家名单出炉:叶杰平、崔鹏等26位华人学者上榜
  17. K均值算法(继续优化中)
  18. 千万不要照着镜子洗头发
  19. u-view2.x picker多列联动遇到的bug
  20. OSRAM欧司朗LED灯珠采购秘籍,收藏这一篇就够了

热门文章

  1. 2021年9月计算机二级考试成绩查询常见问题
  2. 69个办公室常用到的电脑快捷键,苦寻整理出来的,建议收藏一份!
  3. simcom工作记录
  4. 蓝牙测试参数说明--学习记录
  5. 学生小白怎样搭建个人网站?
  6. python获取win10系统声音
  7. python求解欧拉Euler公式
  8. 空数组和null数组
  9. 我测得嗷嗷完美的一个局
  10. 如何做好前端代码规范,让你的代码更丝滑