Nodejs (二)

案例之模拟Apache默认静态文件管理系统

Nodejs 没有Apache所拥有的默认处理静态文件
与检索文件地址的功能,此案例实现此功能
让用户在url地址栏上输入的网址直接匹配到物理文件路径

02.js



/*
*   Nodejs 没有Apache所拥有的默认处理静态文件
*   与检索文件地址的功能,此案例实现此功能
*
* */


var http = require('http');
var fs = require('fs');
var url = require('url');
var path = require('path');

var server = http.createServer(function (req,res) {

    //这里如果不用req.url来if判断,那么用户不管输入什么网址,
    //做的事情都一样

    //获取url地址栏输入的网址
    var pathname = url.parse(req.url).pathname;

    /*
    *   判断此时用户输入的地址是文件夹地址还是文件地址
    *   如果是文件夹地址,那么自动请求这个文件夹中的index.html
    *   js中的indexOf()方法检索括号内的字符串在pathname中出现的位置
    *   出现在哪里就返回其下标值,如果未找到则返回-1
    * */
    if( pathname.indexOf('.') == -1 ){
        pathname += '/index.html';
    }


    /*
    *   匹配url地址栏网址与实际物理文件地址
    *   假如输入的网址是127.0.0.1/image/logo.png
    *   实际请求的是 ./static/image/logo.png
    *   path模块中的方法normalize() 方法检索多余的/并去除
    * */
    var fileURL = './' + path.normalize('./static/' + pathname);
    //获取url地址栏网址的拓展名
    var extname = path.extname(pathname);



    //把文件读出来
    fs.readFile(fileURL,function (err,data) {
        //读完之后做的事情
        if(err){
            //如果文件不存在
            res.writeHead(404,{'Content-Type':'text/html;charset=UTF8'});
            res.end('404,页面没有找到!');
        }
        //读完之后做的事情
        //为了防止异步导致读取的响应头类型为空,此处立即执行函数
        getMime(extname,function (mime) {
            res.writeHead(200,{'Content-Type':mime});
            res.end(data);
        });
    });

});

server.listen(80,'127.0.0.1');



function getMime(extname,callback){
    //读取mime.json文件,得到JSON,根据extname key 返回对应的value
    //读取文件
    fs.readFile('./static/mime.json',function(err,data){
        if(err){
            throw Error('找不到mime.json文件!!!');
            return;
        }
        //将读取的数据object转换成JSON
        var mimeJSON = JSON.parse(data);
        var mime = mimeJSON[extname] || 'text/plain';
        //执行回调函数,mime类型字符串就是它的参数
        callback(mime);
    });
}




在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


模块的概述

在Node.js中,以模块为单位划分所有功能,并且提供了一个完整的模块加载机制,这时的我们可以将应用程序划分为各个不同的部分。
不可能用一个js文件去写全部的业务。肯定要有MVC。

狭义的说,每一个JavaScript文件都是一个模块;而多个JavaScript文件之间可以相互require,他们共同实现了一个功能,他们整体对外,又称为一个广义上的模块。

Node.js中,一个JavaScript文件中定义的变量、函数,都只在这个文件内部有效。当需要从此JS文件外部引用这些变量、函数时,必须使用exports对象进行暴露。使用者要用require()命令引用这个JS文件。

拥有外部接口的js模块
foo.js



var msg = 'Hello World!';
function showInfo(){
    console.log('this is a function');
}

//变量与函数的外部接口
exports.msg = msg;
exports.showInfo = showInfo;



people.js




function People(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
}

People.prototype = {
    sayHello : function(){
        console.log(this.name + this.age + this.sex);
    }
};

//类的外部接口
//此时,People就被视为构造函数,可以用new来实例化了。
module.exports = People;

引入拥有外部接口的模块
03.js



// 引用拥有外部接口的js模块(js文件)

var foo = require('./test/foo.js');
var People = require('./test/people');

//变量与函数的引入
console.log(foo.msg);
foo.showInfo();

//类的引入
var yueqi = new People('越祁','18','女');
yueqi.sayHello();

在这里插入图片描述


node_modules文件夹

node_modules文件夹并不一定在同级目录里面,在任何直接祖先级目录中,都可以。甚至可以放到NODE_PATH环境变量的文件夹中。这样做的好处稍后你将知道:分享项目的时候,不需要带着modules一起给别人。

我们可以使用文件夹来管理模块,比如
1var bar = require(“bar”);
那么Node.js将会默认去寻找node_modules目录下的bar文件夹中的index.js去执行。

每一个模块文件夹中,推荐都写一个package.json文件,这个文件的名字不能改。node将自动读取里面的配置。有一个main项,就是入口文件:

package.json

{
  "name": "abr",
  "version": "1.0.0",
  "dependencies": {
    
  },

  "main":"app.js"
}

package.json文件,要放到模块文件夹node_modules的根目录去

在这里插入图片描述


npm

我们刚才学习了,模块就是一些功能的封装,所以一些成熟的、经常使用的功能,都有人封装成为了模块。并且放到了社区中,供人免费下载。
这个伟大的社区,叫做npm。 也是一个工具名字 node package management
https://www.npmjs.com/

去社区搜索需求,然后点进去,看api。
如果要配置一个模块,那么直接在cmd使用
npm install 模块名字
就可以安装。 模块名字全球唯一。
安装的时候,要注意,命令提示符的所在位置。

在这里插入图片描述

1.我们的依赖包,可能在随时更新,我们永远想保持更新,或者某持某一个版本;
2.项目越来越大的时候,给别人看的时候,没有必要再次共享我们引用的第三方模块。

我们可以用package.json来管理依赖。 在cmd中,使用npm
init可以初始化一个package.json文件,用回答问题的方式生成一个新的package.json文件。
.
使用
npm install
将能安装所有依赖。
npm也有文档,这是package.json的介绍:
https://docs.npmjs.com/files/package.json

关于引用js模块读文件问题

require()别的js文件的时候,将执行那个js文件

require()中的路径,是从当前这个js文件出发,找到别人。而fs是从命令提示符找到别人。
所以,桌面上有一个a.js, test文件夹中有b.js、c.js、1.txt
a要引用b:
var b = require(“./test/b.js”);
b要引用c:
var b = require(“./c.js”);
但是,fs等其他的模块用到路径的时候,都是相对于cmd命令光标所在位置。
所以,在b.js中想读1.txt文件,推荐用绝对路径: (加上__dirname)

在这里插入图片描述

在这里插入图片描述

a.js


var b = require('./test/b.js');

b.js


var fs = require('fs');

// __dirname加上表示绝对路径
fs.readFile(__dirname + '/1.txt',function(err,data){

    if(err){throw err;}
    console.log(data.toString());
});


1.txt

Hello 1.txt

关于模块的引用与模块函数的封装

04.js



var http = require('http');
var router = require('./router');

//创建服务器
var server = http.createServer(function(req,res){
    if(req.url == '/'){
        router.showIndex(req,res);
    }else if(req.url.substr(0,9) == '/student/'){
        router.showStudent(req,res);
    }else{
        router.show404(req,res);
    }

});

server.listen(80,'127.0.0.1');

router.js



//设置外部接口
exports.showIndex = showIndex;
exports.showStudent = showStudent;
exports.show404 = show404;


function showIndex(req,res){
    res.writeHead(200,{'Content-Type':'text/html;charset=UTF8'});
    res.end('我是首页');
}

function showStudent(req,res){
    var id = req.url.substr(9,6);
    res.writeHead(200,{'Content-Type':'text/html;charset=UTF8'});
    res.end('我是学生页面,您输入的学生id为: ' + id);
}

function show404(req,res){
    res.writeHead(404,{'Content-Type':'text/html;charset=UTF8'});
    res.end('404');
}





在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


POST请求

form.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <form action="http://127.0.0.1/dopost" method="post">
        <p>
            姓名 : <input type="text" name="name">
        </p>
        <p>
            性别 :
            <input type="radio" name="sex" value="男">男
            <input type="radio" name="sex" value="女">女
        </p>
        <p>
            爱好:
            <input type="checkbox" name="hobby" value="睡觉" />睡觉
            <input type="checkbox" name="hobby" value="吃饭" />吃饭
            <input type="checkbox" name="hobby" value="足球" />足球
        </p>
        <p>
            图片:
            <input type="file" name="tupian" />
        </p>
        <p>
            <input type="submit" />
        </p>


    </form>


</body>
</html>

05.js



var http = require('http');
//引入字符串api,将二进制数据转换成对象
var querystring = require('querystring');

//创建服务器
var server = http.createServer(function(req,res){
    //设置响应头
    res.writeHead(200,{'Content-Type':'text/html;charset=UTF8'});

   //如果访问的地址是/dopost,并且请求类型是post,则接收表单提交信息
    if(req.url == '/dopost' && req.method.toLowerCase() == 'post'){
        var alldata = '';
        //下面是post请求接收的一个公式
        //node 为了追求极致,它是一个小段一个小段接收的
        //接收了一小段,可能就给别人去服务了,防止一个过大的表单接收信息阻塞了整个进程
        req.addListener('data',function(chunk){
           alldata += chunk;
        });

        //全部传输完毕后
        req.addListener('end',function(){
            var datastring = alldata.toString();
            res.end('提交成功!!!');
            //将datastring转换成一个对象
            var dataObj = querystring.parse(datastring);
            console.log(dataObj);
        });
    }
});

server.listen(80,'127.0.0.1');


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


formidable模块

在npm社区上下载formidable模块包到项目

1.进入社区网址找到下载命令
在这里插入图片描述

2.进入cmd命令行cd到项目文件夹当前命令行位置
在这里插入图片描述

3.查看下载的模块包

在这里插入图片描述

关于图片上传
原生写POST处理,比较复杂,要写两个监听。文件上传业务比较难写。
所以,用第三方模块。formidable。

只要涉及文件上传,那么form标签要加一个属性:
enctype
在这里插入图片描述

form.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <form action="http://127.0.0.1/dopost" enctype="multipart/form-data" method="post">
        <p>
            姓名 : <input type="text" name="name">
        </p>
        <p>
            性别 :
            <input type="radio" name="sex" value="男">男
            <input type="radio" name="sex" value="女">女
        </p>
        <p>
            爱好:
            <input type="checkbox" name="hobby" value="睡觉" />睡觉
            <input type="checkbox" name="hobby" value="吃饭" />吃饭
            <input type="checkbox" name="hobby" value="足球" />足球
        </p>
        <p>
            图片:
            <input type="file" name="tupian" />
        </p>
        <p>
            <input type="submit" />
        </p>


    </form>


</body>
</html>



06.js



var http = require('http');
var formidable = require('formidable');
var util = require('util');

//创建服务器
var server = http.createServer(function(req,res){
   if(req.url == '/dopost' && req.method.toLowerCase() == 'post'){
       //下面是使用npm社区的formidable模块的案例
       //Creates a new incoming form.
       var form = new formidable.IncomingForm();
       //设置文件上传存放地址;
       form.uploadDir = "./uploads";
       //执行里面的回调函数的时候,表单已经全部接收完毕了。
       form.parse(req, function(err, fields, files) {
           if(err){
               throw err;
           }

           console.log(fields);
           console.log(files);
           console.log(util.inspect({fields: fields, files: files}));
           //所有的文本域、单选框,都在fields存放;
           //所有的文件域,files
           res.writeHead(200, {'content-type': 'text/plain;charset=UTF8'});
           res.end("成功");
       });
   }
});

server.listen(80,'127.0.0.1');


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


为上传图片改名

07.js


/**
 * Created by Danny on 2015/9/20 15:35.
 */
var http = require("http");
var formidable = require('formidable');
var util = require("util");
var fs = require("fs");
var sd = require("silly-datetime");
var path = require("path");


//创建服务器
var server = http.createServer(function(req,res){
    //如果你的访问地址是这个,并且请求类型是post
    if(req.url == "/dopost" && req.method.toLowerCase() == "post"){
        //Creates a new incoming form.
        var form = new formidable.IncomingForm();
        //设置文件上传存放地址
        form.uploadDir = "./uploads";
        //执行里面的回调函数的时候,表单已经全部接收完毕了。
        form.parse(req, function(err, fields, files) {
            //if(err){
            //    throw err;
            //}
            //console.log(util.inspect({fields: fields, files: files}));

            //时间,使用了第三方模块,silly-datetime
            var ttt = sd.format(new Date(), 'YYYYMMDDHHmmss');
            var ran = parseInt(Math.random() * 89999 + 10000);
            var extname = path.extname(files.tupian.name);
            //执行改名
            var oldpath = __dirname + "/" + files.tupian.path;
            //新的路径由三个部分组成:时间戳、随机数、拓展名
            var newpath = __dirname + "/uploads/" + ttt + ran + extname;

            //改名
            fs.rename(oldpath,newpath,function(err){
                if(err){
                    throw Error("改名失败");
                }
                res.writeHead(200, {'content-type': 'text/plain'});
                res.end("成功");
            });
        });
    }else if(req.url == "/"){
        //呈递form.html页面
        fs.readFile("./form.html",function(err,data){
            res.writeHead(200, {'content-type': 'text/html'});
            res.end(data);
        })
    }else{
        res.writeHead(404, {'content-type': 'text/html'});
        res.end("404");
    }
});

server.listen(80,"192.168.0.103");


猜你喜欢

转载自blog.csdn.net/qq_39469688/article/details/82995183