美文网首页Node.jsJavaScript
Node.js之常用内置模块

Node.js之常用内置模块

作者: wsgdiv | 来源:发表于2020-12-16 00:49 被阅读0次

    含摘录,非原创

    fs

    fs模块就是文件系统模块,负责读写文件,提供了异步和同步的方法。

    读文件

    异步读文件:

    'use strict';
    
    var fs = require('fs');
    
    fs.readFile('sample.txt', 'utf-8', function (err, data) {
        if (err) {
            console.log(err);
        } else {
            console.log(data);
        }
    });
    

    同步读文件:

    'use strict';
    
    var fs = require('fs');
    
    var data = fs.readFileSync('sample.txt', 'utf-8');
    console.log(data);
    

    可见,原异步调用的回调函数的data被函数直接返回,函数名需要改为readFileSync,其它参数不变。

    如果同步读取文件发生错误,则需要用try...catch捕获该错误:

    try {
        var data = fs.readFileSync('sample.txt', 'utf-8');
        console.log(data);
    } catch (err) {
        // 出错了
    }
    

    写文件

    将数据写入文件是通过fs.writeFile()实现的:

    'use strict';
    
    var fs = require('fs');
    
    var data = 'Hello, Node.js';
    fs.writeFile('output.txt', data, function (err) {
        if (err) {
            console.log(err);
        } else {
            console.log('ok.');
        }
    });
    

    同步:

    'use strict';
    
    var fs = require('fs');
    
    var data = 'Hello, Node.js';
    fs.writeFileSync('output.txt', data);
    

    如果我们要获取文件大小,创建时间等信息,可以使用fs.stat(),它返回一个Stat对象,能告诉我们文件或目录的详细信息

    'use strict';
    
    var fs = require('fs');
    
    fs.stat('sample.txt', function (err, stat) {
        if (err) {
            console.log(err);
        } else {
            // 是否是文件:
            console.log('isFile: ' + stat.isFile());
            // 是否是目录:
            console.log('isDirectory: ' + stat.isDirectory());
            if (stat.isFile()) {
                // 文件大小:
                console.log('size: ' + stat.size);
                // 创建时间, Date对象:
                console.log('birth time: ' + stat.birthtime);
                // 修改时间, Date对象:
                console.log('modified time: ' + stat.mtime);
            }
        }
    });
    

    运行结果如下:

    isFile: true
    isDirectory: false
    size: 181
    birth time: Fri Dec 11 2015 09:43:41 GMT+0800 (CST)
    modified time: Fri Dec 11 2015 12:09:00 GMT+0800 (CST)
    stat()也有一个对应的同步函数statSync()
    

    stream

    在Node.js中,流也是一个对象,我们只需要响应流的事件就可以了:data事件表示流的数据已经可以读取了,end事件表示这个流已经到末尾了,没有数据可以读取了,error事件表示出错了。

    'use strict';
    
    var fs = require('fs');
    
    // 打开一个流:
    var rs = fs.createReadStream('sample.txt', 'utf-8');
    
    rs.on('data', function (chunk) {
        console.log('DATA:')
        console.log(chunk);
    });
    
    rs.on('end', function () {
        console.log('END');
    });
    
    rs.on('error', function (err) {
        console.log('ERROR: ' + err);
    });
    

    注意,data事件可能会有多次,每次传递的chunk是流的一部分数据。
    要以流的形式写入文件,只需要不断调用write()方法,最后以end()结束:

    'use strict';
    
    var fs = require('fs');
    
    var ws1 = fs.createWriteStream('output1.txt', 'utf-8');
    ws1.write('使用Stream写入文本数据...\n');
    ws1.write('END.');
    ws1.end();
    
    var ws2 = fs.createWriteStream('output2.txt');
    ws2.write(new Buffer('使用Stream写入二进制数据...\n', 'utf-8'));
    ws2.write(new Buffer('END.', 'utf-8'));
    ws2.end();
    

    所有可以读取数据的流都继承自stream.Readable,所有可以写入的流都继承自stream.Writable。
    一个Readable流和一个Writable流串起来后,所有的数据自动从Readable流进入Writable流,这种操作叫pipe。

    'use strict';
    
    var fs = require('fs');
    
    var rs = fs.createReadStream('sample.txt');
    var ws = fs.createWriteStream('copied.txt');
    
    rs.pipe(ws);
    

    默认情况下,当Readable流的数据读取完毕,end事件触发后,将自动关闭Writable流。如果我们不希望自动关闭Writable流,需要传入参数:

    readable.pipe(writable, { end: false });

    http

    应用程序并不直接和HTTP协议打交道,而是操作http模块提供的request和response对象。

    'use strict';
    
    // 导入http模块:
    var http = require('http');
    
    // 创建http server,并传入回调函数:
    var server = http.createServer(function (request, response) {
        // 回调函数接收request和response对象,
        // 获得HTTP请求的method和url:
        console.log(request.method + ': ' + request.url);
        // 将HTTP响应200写入response, 同时设置Content-Type: text/html:
        response.writeHead(200, {'Content-Type': 'text/html'});
        // 将HTTP响应的HTML内容写入response:
        response.end('<h1>Hello world!</h1>');
    });
    
    // 让服务器监听8080端口:
    server.listen(8080);
    
    console.log('Server is running at http://127.0.0.1:8080/');
    

    文件服务器
    让我们继续扩展一下上面的Web程序。我们可以设定一个目录,然后让Web程序变成一个文件服务器。要实现这一点,我们只需要解析request.url中的路径,然后在本地找到对应的文件,把文件内容发送出去就可以了。

    解析URL需要用到Node.js提供的url模块,它使用起来非常简单,通过parse()将一个字符串解析为一个Url对象:

    'use strict';
    
    var url = require('url');
    
    console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));
    

    处理本地文件目录需要使用Node.js提供的path模块,它可以方便地构造目录:

    'use strict';
    
    var path = require('path');
    
    // 解析当前目录:
    var workDir = path.resolve('.'); // '/Users/michael'
    
    // 组合完整的文件路径:当前目录+'pub'+'index.html':
    var filePath = path.join(workDir, 'pub', 'index.html');
    // '/Users/michael/pub/index.html'
    

    使用path模块可以正确处理操作系统相关的文件路径。在Windows系统下,返回的路径类似于C:\Users\michael\static\index.html,这样,我们就不关心怎么拼接路径了。
    最后,我们实现一个文件服务器file_server.js

    'use strict';
    
    var
        fs = require('fs'),
        url = require('url'),
        path = require('path'),
        http = require('http');
    
    // 从命令行参数获取root目录,默认是当前目录:
    var root = path.resolve(process.argv[2] || '.');
    
    console.log('Static root dir: ' + root);
    
    // 创建服务器:
    var server = http.createServer(function (request, response) {
        // 获得URL的path,类似 '/css/bootstrap.css':
        var pathname = url.parse(request.url).pathname;
        // 获得对应的本地文件路径,类似 '/srv/www/css/bootstrap.css':
        var filepath = path.join(root, pathname);
        // 获取文件状态:
        fs.stat(filepath, function (err, stats) {
            if (!err && stats.isFile()) {
                // 没有出错并且文件存在:
                console.log('200 ' + request.url);
                // 发送200响应:
                response.writeHead(200);
                // 将文件流导向response:
                fs.createReadStream(filepath).pipe(response);
            } else {
                // 出错了或者文件不存在:
                console.log('404 ' + request.url);
                // 发送404响应:
                response.writeHead(404);
                response.end('404 Not Found');
            }
        });
    });
    
    server.listen(8080);
    
    console.log('Server is running at http://127.0.0.1:8080/');
    

    crypto

    crypto模块的目的是为了提供通用的加密和哈希算法。
    MD5是一种常用的哈希算法,用于给任意数据一个“签名”。这个签名通常用一个十六进制的字符串表示
    Hmac算法也是一种哈希算法,它可以利用MD5或SHA1等哈希算法。不同的是,Hmac还需要一个密钥。只要密钥发生了变化,那么同样的输入数据也会得到不同的签名,因此,可以把Hmac理解为用随机数“增强”的哈希算法。
    AES是一种常用的对称加密算法,加解密都用同一个密钥。crypto模块提供了AES支持,但是需要自己封装好函数,便于使用
    DH算法是一种密钥交换协议,它可以让双方在不泄漏密钥的情况下协商出一个密钥来。DH算法基于数学原理
    RSA算法是一种非对称加密算法,即由一个私钥和一个公钥构成的密钥对,通过私钥加密,公钥解密,或者通过公钥加密,私钥解密。其中,公钥可以公开,私钥必须保密。
    crypto模块也可以处理数字证书。数字证书通常用在SSL连接,也就是Web的https连接。一般情况下,https连接只需要处理服务器端的单向认证,如无特殊需求(例如自己作为Root给客户发认证证书),建议用反向代理服务器如Nginx等Web服务器去处理证书。

    相关文章

      网友评论

        本文标题:Node.js之常用内置模块

        本文链接:https://www.haomeiwen.com/subject/nrwggktx.html