文件路径
操作文件的路径使用注意事项:
- 如果是以
/
开头的路径,则就是去执行当前脚本所属的磁盘根路径去找 - 如果是以
C:/dev/nvm/settings.txt
,则直接去找该绝对路径 - 如果是以
./
或者../
开头的,则是相对于执行 node 命令的时候所处的路径
1 | const fs = require('fs'); |
如果使用 C:\Users\mhq\Desktop> node code/02_文件路径.js
这样执行 node 命令:
该文件中的相对路径是去执行node命令的目录地方去找了 'C:\Users\mhq\Desktop\README.md
又如:C:\Users\mhq> node .\Desktop\code\02_文件路径.js
找了这样 C:\Users\mhq\README.md
的目录
想要解决上面的问题:
每一个模块中都提供了两个属性: __dirname
和 __filename
所以,如果是操作相对路径的文件,最好把相对路径转为绝对路径。
但是绝对路径又不能写死,可以使用每一个文件模块中都提供了两个属性:__dirname
和 __filename
。
__dirname
用来获取当前文件模块所属目录的绝对路径__filename
用来获取当前文件的绝对路径,这个属性用的比较少
然后在执行 node 命令,不会受路径影响。
__dirname
相对于当前所在文件,找到它的绝对路径,假如下面这段代码在 02.js
这个文件中,那么 __dirname
就是找的 02.js
的绝对路径。而这个 README.md
文件是和 02.js
同级,如果 02.js
在 README.md
的上一级,那么只需要加上 ../
就可以自动拼接了。
1 | const fs = require('fs'); |
注意:加载自己写的相对路径模块不受执行 node 命令所处目录影响,也就是说,加载文件模块还是使用相对路径
node 中使用模板引擎
app.js
1 | const http = require('http'); |
router.js
1 | const path = require('path'); |
hander.js
1 | const fs = require('fs'); |
./views/index.html
1 |
|
现在的问题是要使项目运行起来,不知道项目的入口文件。
如何解决? 利用某种规则。可以写一些 npm 运行脚本。如:package.json
中的 "script"
。
在 “script” 下加 "start": "node app.js"
。
现在启动网站直接可以使用 npm start
直接启动项目。其中start
是在终端中要执行的命令名称。
package.json
1 | { |
使用模板引擎
在浏览器中使用模板引擎
1 |
|
在 node 中使用模板引擎
在 node 中,模板引擎的使用方式和浏览器是一样的。
只不过模板字符串的存储方式变了,因为 node
中没有DOM
,没有 script
标签的概念。
但是 node 支持文件操作,所以我们把模板字符串放到文件中。
使用的时候,通过 fs.readFile
读取出来就可以了。
.js 文件
1 | const _ = require('underscore'); |
tpl.mhq
1 | <% arr.forEach(function (item) { %> |
使用模板引擎处理别的字符串
.js 文件
1 | const fs = require('fs'); |
data.json
1 | [ |
result.txt
1 | <% users.forEach(function (user) { %> |
处理添加相册
GET
/album/add?albumName=xxx&key=xxx
表单 GET 提交(表单的 method 属性默认就是 get):
表单会将表单中所有具有 name 属性的 input 按照: name=input-value&name1=input-value2&xxx=xxx
, 拼接完之后,找到自己的 action
(就是请求路径), 然后在 action
之后 加一个 ? ,后面跟上拼接好的查询字符串
最后,发起请求 albumName=xxx&xxx=xxx
/album/add?albumName=xxx&xxx=xxx
appjs
1 | const http = require('http') |
index.html
1 |
|
album.html
1 |
|
router.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43const path = require('path');
const url = require('url');
const handler = require('./handler');
module.exports = function (req, res) {
// 指定第二个参数,parse 方法会将查询字符串解析为一个对象挂载给返回结果的 query 属性
// 该方法,会将一个完整的 url 路径解析为一个对象,方便我们取各个部分的数据
const urlObj = url.parse(req.url, true);
// 拿到请求路径,不包含查询字符串
const pathname = urlObj.pathname;
// 拿到通过 url.parse 方法解析出来的查询字符串(已经自动转为对象了)
const queryObj = urlObj.query;
// 拿到当前请求方法
const method = req.method.toLowerCase();
// 在这里,将解析到的查询字符串以属性的形式挂载给 req 请求对象
// 在后面的处理方法中就可以直接通过 req.query 来获取查询字符串中的数据了
req.query = queryObj || {};
// 302 重定向
// 浏览器收到 302 状态码的时,浏览器会自动找响应报文中的 Location,然后对 Location 指向的地址发起请求
// 在这里给 res 对象挂载一个 redirect 方法,在后续的处理中就可以直接使用该方法,就可以实现重定向跳转
res.redirect = url => {
res.writeHead(302, {
'Location': url;
})
res.end();
}
// 一个请求其实就是对应一个处理函数,每一个请求处理函数无非都需要用到 req 对象和 res 对象
// 所以 handler 中都定义成接收 req 和 res 的一个一个的小函数,用来处理对应的请求
if (pathname === '/') {
handler.showIndex(req, res);
} else if (method === 'get' && (pathname.startsWith('/public/') || pathname.startsWith('/uploads/') || pathname.startsWith('/node_modules/'))) {
handler.showPublic(req, res);
} else if (method === 'get' && pathname === '/album/add') {
handler.doAddAlbum(req, res);
} else if (method === 'get' && pathname === '/album') {
handler.showAlbum(req, res);
} else if (method === 'post' && pathname === '/upload') {
handler.doUpload(req, res);
} else if (method === 'get' && pathname === '/register') {
handler.showRegister(req, res);
} else if (method === 'post' && pathname === '/register') {
handler.doRegister(req, res);
}
}
handler.js
1 | const fs = require('fs'); |
config.js1
2
3
4
5const path = require('path');
module.exports = {
uploadDir: path.join(__dirname, 'uploads'),
viewPath : path.join(__dirname, 'views')
};
处理普通表单 POST 提交(没有文件的表单)
表单会将表单中的所有具有 name 的 input 中的 name 和 value 按照 name=value&name=value
,这样的形式拼接成一个查询字符串,然后将查询字符串放到请求报问体中。
- 请求头
- 请求首行
- 请求首部字段
- 空行
- 请求体
name=value&name=value
处理有文件的表单 POST 提交
- 请求方法必须是 post
- 将表单的 enctype 设置为 multipart/form-data
- 表单会把普通字段(不是文件,具有name的input)和文件,否放到请求报问体中。
注意:这里的请求报问体中就不是查询字符串了,所以后台通过查询字符串的解析方式就解析不到了
如何解析:
- 在 Node 后台,可以使用一个第三方包:formidable 来辅助解析有文件的表单提交
- 使用文档可以查看:
album/node_modules/formidable/Readme.md
简单登录页(仅仅用来案例演示)
1 |
|