18.4.25Node初始

https://www.nodebeginner.org/index-zh-cn.html  Node入门:



var http = require("http");
function onRequest(request, response) {  
        console.log("Request received.");  
        response.writeHead(200, {"Content-Type": "text/plain"});  
        response.write("Hello World");  
        response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");


注意:在 onRequest (我们的回调函数)触发的地方,我用 console.log 输出了一段文本。在HTTP服务器开始工作之后,也输出一段文本。  当我们与往常一样,运行它node server.js时,它会马上在命令行上输出“Server has started.”。当我们向服务器发出请求(在浏览器访问http://localhost:8888/),“Request received.”这条消息就会在命令行中出现。
这就是事件驱动的异步服务器端JavaScript和它的回调啦!(请注意,当我们在服务器访问网页时,我们的服务器可能会输出两次“Request received.”。那是因为大部分浏览器都会在你访问 http://localhost:8888/ 时尝试读取 http://localhost:8888/favicon.ico )

当回调启动,我们的 onRequest() 函数被触发的时候,有两个参数被传入: request 和 response   它们是对象,你可以使用它们的方法来处理HTTP请求的细节,并且响应请求(比如向发出请求的浏览器发回一些东西)
所以我们的代码就是:当收到请求时,使用 response.writeHead() 函数发送一个HTTP状态200和HTTP头的内容类型(content-type),使用 response.write() 函数在HTTP相应主体中发送文本“Hello World"。最后,我们调用 response.end() 完成响应。目前来说,我们对请求的细节并不在意,所以我们没有使用 request 对象。

服务端的模块放在哪里?
我们现在就来谈谈怎么把server.js变成一个真正的Node.js模块,使它可以被我们(还没动工)的 index.js 主文件使用。
Node.js中自带了一个叫做“http”的模块,我们在我们的代码中请求它并把返回值赋给一个本地变量  var http = require("http");  .....  http.createServer(...);
把某段代码变成模块意味着我们需要把我们希望提供其功能的部分 导出 到请求这个模块的脚本
目前,我们的HTTP服务器需要导出的功能非常简单,因为请求服务器模块的脚本仅仅是需要启动服务器而已。
 


我们把我们的服务器脚本放到一个叫做 start 的函数里,然后我们会导出这个函数。
var http = require("http");
function start() {
  function onRequest(request, response) {
    console.log("Request received.");
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }
 http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}
exports.start = start;
这样,我们现在就可以创建我们的主文件 index.js 并在其中启动我们的HTTP了,虽然服务器的代码还在 server.js 中。
index.js:
var server = require("./server");
server.start();
正如你所看到的,我们可以像使用任何其他的内置模块一样使用server模块:请求这个文件并把它指向一个变量,其中已导出的函数就可以被我们使用了


我们现在可以把我们的应用的不同部分放入不同的文件里,并且通过生成模块的方式把它们连接到一起了。


处理不同的HTTP请求在我们的代码中是一个不同的部分,叫做“路由选择”——那么,我们接下来就创造一个叫做 路由 的模块吧。


我们要为路由提供请求的URL和其他需要的GET及POST参数,随后路由需要根据这些数据来执行相应的代码(这里“代码”对应整个应用的第三部分:一系列在接收到请求时真正工作的处理程序)。
我们需要的所有数据都会包含在request对象中,该对象作为onRequest()回调函数的第一个参数传递。但是为了解析这些数据,我们需要额外的Node.JS模块,它们分别是urlquerystring模块。


现在我们来给onRequest()函数加上一些逻辑,用来找出浏览器请求的URL路径:


 

为了使整个过程非阻塞,Node.js会将POST数据拆分成很多小的数据块,然后通过触发特定的事件,将这些小数据块传递给回调函数。这里的特定的事件有data事件(表示新的小数据块到达了)以及end事件(表示所有的数据都已经接收完毕)。

 

我们需要告诉Node.js当这些事件触发的时候,回调哪些函数。怎么告诉呢? 我们通过在request对象上注册监听器(listener) 来实现。这里的request对象是每次接收到HTTP请求时候,都会把该对象传递给onRequest回调函数。

如下所示:

request.addListener("data", function(chunk) {   // called when a new chunk of data was received }); request.addListener("end", function() {   // called when all chunks of data have been received });
 

在我看来,获取所有来自请求的数据,然后将这些数据给应用层处理,应该是HTTP服务器要做的事情。因此,我建议,我们直接在服务器中处理POST数据,然后将最终的数据传递给请求路由和请求处理器,让他们来进行进一步的处理。

因此,实现思路就是: 将dataend事件的回调函数直接放在服务器中,在data事件回调中收集所有的POST数据,当接收到所有数据,触发end事件后,其回调函数调用请求路由,并将数据传递给它,然后,请求路由再将该数据传递给请求处理程序。


本地文件显示在浏览器中:用一个叫fs的模块

添加/showURL的请求处理程序,该处理程序直接硬编码将文件/tmp/test.png内容展示到浏览器中。当然了,首先需要将该图片保存到这个位置才行。

 

var querystring = require("querystring"),
    fs = require("fs");

function start(response, postData) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" '+
    'content="text/html; charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" method="post">'+
    '<textarea name="text" rows="20" cols="60"></textarea>'+
    '<input type="submit" value="Submit text" />'+
    '</form>'+
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response, postData) {
  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("You've sent the text: "+
  querystring.parse(postData).text);
  response.end();
}

function show(response, postData) {
  console.log("Request handler 'show' was called.");
  fs.readFile("/tmp/test.png", "binary", function(error, file) {
    if(error) {
      response.writeHead(500, {"Content-Type": "text/plain"});
      response.write(error + "\n");
      response.end();
    } else {
      response.writeHead(200, {"Content-Type": "image/png"});
      response.write(file, "binary");
      response.end();
    }
  });
}

exports.start = start;
exports.upload = upload;
exports.show = show; querystring = require("querystring"),
    fs = require("fs");

function start(response, postData) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" '+
    'content="text/html; charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" method="post">'+
    '<textarea name="text" rows="20" cols="60"></textarea>'+
    '<input type="submit" value="Submit text" />'+
    '</form>'+
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response, postData) {
  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("You've sent the text: "+
  querystring.parse(postData).text);
  response.end();
}

function show(response, postData) {
  console.log("Request handler 'show' was called.");
  fs.readFile("/tmp/test.png", "binary", function(error, file) {
    if(error) {
      response.writeHead(500, {"Content-Type": "text/plain"});
      response.write(error + "\n");
      response.end();
    } else {
      response.writeHead(200, {"Content-Type": "image/png"});
      response.write(file, "binary");
      response.end();
    }
  });
}

exports.start = start;
exports.upload = upload;
exports.show = show;

我们还需要将这新的请求处理程序,添加到index.js中的路由映射表中:

 

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;
handle["/show"] = requestHandlers.show;

server.start(router.route, handle); server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;
handle["/show"] = requestHandlers.show;

server.start(router.route, handle);

重启服务器之后,通过访问http://localhost:8888/show,就可以看到保存在/tmp/test.png的图片了。

上传文件:

在上述代码中加一个input标签:

 

  var body = '<html>'+
   ...
    '<input type="file" name="upload">'+
   ...var body = '<html>'+
   ...
    '<input type="file" name="upload">'+
   ...

这里有这样一个问题: 我们需要在upload处理程序中对上传的文件进行处理,这样的话,我们就需要将request对象传递给node-formidable的form.parse函数。

但是,我们有的只是response对象和postData数组。看样子,我们只能不得不将request对象从服务器开始一路通过请求路由,再传递给请求处理程序。 或许还有更好的方案,但是,不管怎么说,目前这样做可以满足我们的需求。

到这里,我们可以将postData从服务器以及请求处理程序中移除了 —— 一方面,对于我们处理文件上传来说已经不需要了,另外一方面,它甚至可能会引发这样一个问题: 我们已经“消耗”了request对象中的数据,这意味着,对于form.parse来说,当它想要获取数据的时候就什么也获取不到了。(因为Node.js不会对数据做缓存)

我们从server.js开始 —— 移除对postData的处理以及request.setEncoding (这部分node-formidable自身会处理),转而采用将request对象传递给请求路由的方式:

接下来是 router.js —— 把postData改成request对象:

现在,request对象就可以在我们的upload请求处理程序中使用了。node-formidable会处理将上传的文件保存到本地/tmp目录中,而我们需要做的是确保该文件保存成/tmp/test.png。 没错,我们保持简单,并假设只允许上传PNG图片

这里采用fs.renameSync(path1,path2)来实现。要注意的是,正如其名,该方法是同步执行的, 也就是说,如果该重命名的操作很耗时的话会阻塞

requestHandlers.js所示:

 

 

NODE调用shell:

demo.js:

const callfile = require('child_process');
const newpassword = 'newpwd';
callfile.exec('./a.sh one two three',function (err, stdout, stderr) {
    console.dir(arguments);
});

a.sh:

echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

输出:

{ '0': null,
  '1': '第一个参数为:one\n第二个参数为:two\n第三个参数为:three\n',
  '2': '' }

监听器的添加:

使用 emitter.emit(eventName[, ...args]) 按照监听器注册的顺序,同步地调用每个注册到名为 eventName 的事件的监听器,并传入提供的参数。如果事件有注册监听返回 true,否则返回 false。

参数说明:

  • eventName :事件名称
  • args:传递的参数,多个,类型为任意。
    var events = require('events');// 引入 events 模块
    var emitter = new events.EventEmitter();// 创建 emitter 对象
    var callback1 = function(arg1,arg2){//定义一个回调函数
        console.log('hello ',arg1,arg2);
    }
    var callback2 = function(arg3,arg4){
        console.log('world',arg3,arg4);
    }
    emitter.on('connection',callback1)//为 connection 事件注册监听器  on=addListener
    emitter.on('connection',callback2)
    //默认情况下,事件监听器会按照添加的顺序依次调用。emitter.prependListener() 方法可用于将事件监听器添加到监听器数组的开头
    emitter.prependListener('connection',() => console.log('yilianjie2'))
    //setTimeout(function(){
        emitter.emit('connection','12','34');//调用监听器
    //},1000)
    
    
    
    //结果:
    yilianjie2
    hello  12 34
    world 12 34

    使用 eventEmitter.once(eventName, listener) 可以注册最多可调用一次的监听器。

var events = require('events');// 引入 events 模块
var emitter = new events.EventEmitter();// 创建 emitter 对象

var n=0;
emitter.once('connection',function(){
++n;
console.log('调用第'+n+'次')
})//为 connection 事件注册监听器

emitter.emit('connection');//调用监听器
emitter.emit('connection');
emitter.emit('connection');


结果:调用第一次

emitter.prependOnceListener() 方法可用于将事件监听器添加到监听器数组的开头。用法与我们前面所学的emitter.prependListener() 方法一致,区别在于这个方法注册的监听器最多只能调用一次

监听器的移除:

使用 emitter.removeListener(eventName, listener) 移除监听器。

参数说明:

  • eventName 事件名称
  • listener 监听器也就是回调函数名称。
var events = require('events');// 引入 events 模块
var emitter = new events.EventEmitter();// 创建 emitter 对象
var callback = function(){  //定义一个回调函数
    console.log('syl');
}

emitter.on('connection',callback)//为 connection 事件注册监听器
emitter.removeListener('connection',callback)//为 connection 事件移除监听器
emitter.emit('connection');//调用监听器

结果: 什么都没有

注:removeListener() 最多只会从监听器数组中移除一个监听器。我们可以多次调用 removeListener() 的方式来一个个的移除我们需要移除掉的监听器。

一旦事件被触发,所有绑定到该事件的监听器都会按顺序依次调用。也就是说在事件触发之后、且最后一个监听器执行完成之前,removeListener() 或 removeAllListeners() 不会从 emit() 中移除它们

// 引入 events 模块
var events = require('events');
// 创建 emitter 对象
var emitter = new events.EventEmitter();
//定义回调函数
var callback1 =  function() {
  console.log('我是1');
  emitter.removeListener('connection',callback2);
};
var callback2 =  function() {
  console.log('我是2');
};
//为 connection 事件注册监听器
emitter.on('connection',callback1);
emitter.on('connection',callback2);
//第一次调用监听器,callback1 移除了监听器 callback2,但它依然会被调用。触发时内部的监听器数组为 [callback1, callback2]
emitter.emit('connection');
//第二次调用监听器,此时 callback2 已经被移除了。内部的监听器数组为 [callback1]
emitter.emit('connection');

结果: 我是1
      我是2
      我是1

emitter.off(eventName, listener) 是 emitter.removeListener() 的别名。

使用 emitter.removeAllListeners([eventName]) 移除全部监听器或指定的 eventName 事件的监听器。

// 引入 events 模块
var events = require('events');
// 创建 emitter 对象
var emitter = new events.EventEmitter();
//定义回调函数
var callback1 =  function() {
  console.log('我是1');
};
var callback2 =  function() {
  console.log('我是2');
};
//为 connection 事件注册监听器
emitter.on('connection',callback1);
emitter.on('connection',callback2);
//移除connection事件的所有监听器
emitter.removeAllListeners('connection');
//调用监听器
emitter.emit('connection');

结果:什么都没有

emitter.setMaxListeners(n)

使用 emitter.setMaxListeners(n) 设置同一事件的监听器最大绑定数。默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告,这有助于我们发现内存泄露。显然实际编码中并不是所有的事件都要限制 10 个监听器。 emitter.setMaxListeners() 方法可以为指定的 EventEmitter 实例修改限制。当值设为 Infinity(或 0)表示不限制监听器的数量。

查看事件绑定的监听器个数:

emitter.listenerCount(eventName)

//引入events模块
var events = require('events');
//创建emitter对象
var emitter = new events.EventEmitter();
//定义回调函数
var callback1 = function(){
    console.log('我是callback1');
}
var callback2 = function(){
    console.log('我是callback2')
}
//为connection事件注册监听器
emitter.on('connection',callback1);
emitter.on('connection',callback2);
//查看connection事件绑定的监听器个数
var num = emitter.listenerCount('connection');
console.log(num);

结果:2

error事件:
 

当 EventEmitter 实例出错时,应该触发 'error' 事件。

如果没有为 'error' 事件注册监听器,则当 'error' 事件触发时,会抛出错误、打印堆栈跟踪、并退出 Node.js 进程。

//引入events模块
var events = require('events');
//创建emitter对象
var emitter = new events.EventEmitter();
//设置监听器
emitter.on('error',(err) => {
    console.error('错误信息');
})
emitter.emit('error')

结果:错误信息

Node.js http模块:

//引入http模块
var http = require('http');
//创建服务器
http.createServer(function(req,res){
    //发送http头部
    //http状态值:200 : ok
    //内容类型:text/plain
    res.writeHead(200,{'Content-Type':'text/plain'});
    //发送响应数据 hello
    res.end("hello")
}).listen(8080);
//终端打印信息
console.log("server running at http://127.0.0.1:8080/");

response 对象常用的方法有:

  1. response.writeHead(statusCode[, statusMessage][, headers])。表示向请求发送响应头。

参数说明:

  • statusCode:状态码,是一个 3 位 HTTP 状态码,如 404 表示网页未找到,200 表示正常。

  • statusMessage: 可选地,可以将用户可读的 statusMessage 作为第二个参数。

  • headers:响应头。也就是设置 Content-Type 的值,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件。常用值有:(1)text/html:HTML 格式(2)text/plain:纯文本格式(3)application/x-www-form-urlencoded:数据被编码为名称/值对,这是标准的编码格式。

    response.writeHead(200,{'Content-Type':'text/plain;charset=UTF-8'});
    此方法只能在消息上调用一次,并且必须在调用response.end()之前调用他
  1. response.write() 发送一块响应主体,也就是说用来给客户端发送响应数据。可以直接写文本信息,也可以写我们的 html 代码,注意要设置 Content-Type 的值 。write 可以使用多次,但是最后一定要使用 end 来结束响应,否则客户端会一直等待。

  2. response.end() 此方法向服务器发出信号,表示已发送所有响应头和主体,该服务器应该视为此消息完成。必须在每个响应上调用方法 response.end()。

Node.js中的fs模块提供了一个api 用于与文件系统进行交互,导入文件系统模块的语法如下:

   var fs=require('fs')

异步打开文件(node.js是同步的,所以代码最好是异步,防止服务器停止响应) fs.open(path,flags[,mode],callback);

例子:创建一个input.txt文件,不写任何内容,然后创建file.js文件打开input.txt文件进行读写

// 引入fs模块
var fs = require("fs");
// 异步打开文件
fs.open('input.txt', 'r+', function(err, fd) {  //r+ 打开文件用于读取和写入,文件不存在发生异常
   if (err) {
       return console.error(err);
   }
  console.log("文件打开成功!");
});

//结果:文件打开成功!

同步打开文件: fs.openSync(path,flags[,mode])//用的极少

关闭文件:

异步关闭文件:fs.close(fd,callback);   //fd是通过fs.open()方法返回的文件描述符   

例子:新建一个input.txt文件,内容可有可无,新建一个closeFile.js文件:

var fs = require("fs");
fs.open('input.txt','r+',function(err,fd){
    if(err){
        return console.error(err)
    }
    console.log("文件打开成功")
    //异步关闭文件
    fs.close(fd,function(err){
        if(err){
            console.log(err)
        }
        console.log("文件关闭成功")
    })
})
//结果:文件打开成功  文件关闭成功

fs.read和fs.write读写文件:

异步读取文件:fs.read(fd,buffer,offset,length,position,callback)

fd:通过fs.open()返回的文件描述符

buffer:是数据写入的缓冲区

offset:是缓冲区中开始写入的偏移量,一般是0

length:整数,指定要读取的字节数

position:指定从文件中开始读取的位置,如果position为null,则从当前位置读取数据,并更新文件位置

callback:回调函数,有三个参数err,byteRead,buffer.err是错误信息,byteRead表示读取的字节数,buffer为缓冲区对象

例子:

新建一个input.txt文件,写入 hello wqq 新建一个js文件

var fs = require("fs");
fs.open('input.txt','r+',function(err,fd){
    if(err){
        return console.error(err)
    }
    console.log("文件打开成功")
    console.log("准备读取文件:")
    //创建一个大小为1024字节的缓存区
    var buf = Buffer.alloc(1024);
    //异步读取文件
    fs.read(fd,buf,0,buf.length,0,function(err,bytes,buf){
        if(err){
            console.log(err)
        }
        console.log(bytes + "字节被读取");
        //仅输出读取的字节
        if(bytes>0){
            console.log(buf.slice(0,bytes).toString());
        }
        //异步关闭文件
        fs.close(fd,function(err){
            if(err){
                console.log(err)
            }
            console.log("文件关闭成功")
        })
    })
})

//
文件打开成功
准备读取文件:
9字节被读取
hello wqq
文件关闭成功

异步写入文件fs.write(fd,buffer,offset,length,position,callback);

fd:从指定的文件写入数据

buffer:是数据写入的缓冲区

offset:指定要写入的buffer部分

length:一个整数,指定要写入的字节数

position:指定应该写入此数据的文件开头的偏移量,如果typeof position!=='number',则从当前位置写入数据

callback:回调有三个参数(err,bytesWritten,buffer),其中bytesWritten指定从buffer写入的字节数

例子:

var fs = require("fs");
fs.open('input.txt','a',function(err,fd){
    if(err){
        return console.error(err)
    }
    console.log("文件打开成功")
    console.log("准备写入文件:")
    //新写入内容为 hello world
    var buf = Buffer.from(new String(' hello world'));
    //异步写入文件
    fs.write(fd,buf,0,12,0,function(err,bytes,buf){
        if(err){
            throw err;
        }
        console.log("写入成功");
        //打印出buffer中存入的数据
        console.log(bytes+"字节被写入");
        console.log(buf.slice(0,bytes).toString())

        //异步关闭文件
        fs.close(fd,function(err){
            if(err){
                console.log(err)
            }
            console.log("文件关闭成功")
        })
    })
})
//
文件打开成功
准备写入文件:
写入成功
12字节被写入
 hello world
文件关闭成功

还有一种语法:fs.write(fd.string[,position[,encoding]],callback);

fd:从指定的文件写入数据

string:写入的数据,如果不是字符串,则该值将被强制转换为字符串

position 指定应该写入此数据的文件开头的偏移量,如果typeof position!=='number' 则从当前位置写入数据

encoding:指定字符串的编码,默认为'utf-8'

callback:回调有三个参数(err,written,string),其中written指定字符串中已写入文件的字节数,写入的字节数与字符串的字符数是不同的

例子:

var fs = require("fs");
fs.open('input.txt','a',function(err,fd){
    if(err){
        return console.error(err)
    }
    console.log("文件打开成功")
    console.log("准备写入文件:")
    //新写入内容为 hello world
    var data = " hello world";
    //异步写入文件
    fs.write(fd,data,0,'utf-8',function(err,bytes,buf){
        if(err){
            return console.error(err)
        }
        console.log(bytes+'字节被写入');
        console.log(buf)
    
        //异步关闭文件
        fs.close(fd,function(err){
            if(err){
                console.log(err)
            }
            console.log("文件关闭成功")
        })
    })
})
//结果:
文件打开成功
准备写入文件:
12字节被写入
 hello world
文件关闭成功

readFile读取文件:

异步读取文件:fs.readFile(path,[options],callback);

path:文件名或文件描述符

options:改参数是一个对象,包含{encoding,flag}.encoding默认值为null,flag默认值为'r'

callback:回调函数

例子:

新建一个input.txt文件,内容:

hello wqq

hello world

新建一个readFile.js文件:

var fs = require('fs');
//读取文件
fs.readFile('input.txt','utf-8',function(err,data){
    if(err){
        throw err;
    }
    //读取文件成功
    //console.log(data.toString());   //没有utf-8参数的情况下,输出的是二进制,需要转化
    console.log(data);
})

//结果:
hello wqq
hello world

fs.readFileSync(filename,[options])是readFile的同步方法

writeFile写入文件:

异步写入文件的:

fs.writeFile(file,data,[options],callback);

file:文件名或文件描述符

data:要写入文件的数据,可以是String,或Buffer对象

options:该参数是一个对象,包含{encoding,mode,flag}.encoding的默认值是'utf-8' mode的默认值是0o666,flag默认是'w'

callback:回调函数

例子:

新建一个writeFile.js文件:

var fs = require('fs');
//写入文件内容,如果不存在会创建一个
//写入时先清空文件
fs.writeFile('text.txt','hello wqq',function(err){
    if(err){
        throw err;
    }
    console.log('Saved.');
    //写入成功后读取测试
    fs.readFile('text.txt','utf-8',function(err,data){
        if(err){
            throw err;
        }
        console.log(data);
    })
})
//
Saved.
hello wqq   //不会叠加

可以通过设置flag的值,来改变默认的写入方式,比如设置为'a',追加数据到文件中.

var fs = require('fs');
//写入文件内容,如果不存在会创建一个
//传递了追加参数{'flag':'a'}
fs.writeFile('text.txt',' hello what is your name',{'flag':'a'},function(err){
    if(err){
        throw err;
    }
    console.log('Saved.');
    //写入成功后读取测试
    fs.readFile('text.txt','utf-8',function(err,data){
        if(err){
            throw err;
        }
        console.log(data);
    })
})
//
Saved.
hello wqqhello what is your name   //运行一次会叠加一次

异步追加内容还有一个方法fs.appendFile(),自己了解

异步获取文件信息的格式为:

fs.stat(path,callback);

path:文件路径

callback回调函数,带有两个参数如:(err,stats) stats是fs.Stats对象

如出现错误,则err.code是常见的系统错误之一

不建议在调用fs.open() fs.readFile()或fs.writeFile()之前使用fs.stat()检测文件是否存在,而是,应该直接打开,读取或写入文件,并在文件不可用时处理引发的错误

fs.stat(path)执行后,会将stat类的实例返回给其他回调函数,可以通过stats类中的提供方法判断文件的相关属性,例如判断是否为文件

例子:

var fs=require('fs');

fs.stat('/home/project/fs.js',function(err,stats){

      console.log(stats.isFile());

})

//结果:true

截取文件:

fs.ftruncate(fd[,len],callback);

fd:通过fs.open()方法返回的文件描述符

len:文件内容截取的长度,默认为0

callback:除了可能的异常,完成回调没有其他参数

例子

新建test.txt的文件写入:hello wqq,新建ftr.js

var fs=require('fs');

fs.open('test.txt','r+',function(err,fd){
if(err){
    return console.error(err);
}
console.log("文件打开成功");
console.log("截取6字节内的文件内容,超出部分将被去除")
//截取文件
var buf=Buffer.alloc(1024);
fs.ftruncate(fd,6,function(err){
    if(err){
        console.log(err)
    }
    console.log("文件截取成功")

    console.log("读取相同文件")
    fs.read(fd,buf,0,buf.length,0,function(err,bytes){
        if(err){
            console.log(err)
        }
        //仅输出读取的字节
        if(bytes>0){
            console.log(buf.slice(0,bytes).toString());
        }
        //关闭文件
        fs.close(fd,function(err){
            if(err){
                console.log(err);
            }
            console.log("文件关闭成功")
        })
    })
})
})
//结果:
文件打开成功
截取6字节内的文件内容,超出部分将被去除
文件截取成功
读取相同文件
hello 
文件关闭成功

删除文件:

fs.unlink(path,callback)

path:文件路径

callback:除了可能的异常,完成回调没有其他参数

例子:

var fs=require('fs');
fs.unlink('test.txt',function(err){
    if(err){
        return console.error(err);
    }
    console.log("文件删除成功");
})
//结果:文件删除成功

异步修改文件名的语法:fs.rename(oldpath,newpath,callback)

oldpath:原来的文件名字

newpath:新的文件名字

callback:回调函数,除了可能的异常,完成回调没有其他参数

例子:新建一个old.txt rename.js

var fs=require('fs');
//异步修改文件的名字
fs.rename('old.txt','new.txt',function(err){
    if(err){
        throw err;
    }
    console.log("重命名完成");
})
//结果:重命名完成

异步新建目录:  fs.mkdir(path[,options],callback);

path:文件路径

options:有两个参数,recursive表示是否以递归的方式创建目录,默认为false.mode设置目录权限,windows上不支持

callback:回调函数,除了可能的异常,完成回调没有其他参数

var fs=require('fs');
console.log('创建目录./test');
//异步创建目录
fs.mkdir('./test/',function(err){
    if(err){
        return console.error(err)
    }
    console.log("目录创建成功")
})
//结果:
创建目录./test
目录创建成功

异步读取目录: fs.readdir(path[,options],callback);

path:文件路径

options:有两个参数encoding ,withFileTypes .encoding默认值是utf8  withFileTypes默认值是false

callback:回调函数,回调函数带有两个参数err,files,err为错误信息,files为目录下的文件数组列表

例子:

var fs=require('fs');
fs.readdir('./test',function(err,files){
    if(err){throw err;}
    //files是个数组
    //每个元素是此目录下的文件或文件夹的名称
    console.log(files);
})
//读取project目录
fs.readdir('../project',function(err,files){
    if(err){
        throw err;
    }
    console.log(files)
})
//结果:
[]
[ 'fs.js', 'new.txt', 'test' ]

异步删除目录:fs.rmdir(path,callback)

例子

var fs=require('fs');
//执行前创建一个空的test目录,用我们之前创建好的
console.log("准备删除目录./test")
fs.rmdir('./test',function(err){
    if(err){
        return console.error(err);
    }
})
//结果:
准备删除目录./test

Node.js的web框架,Express:

npm install express

例子:

var express = require('express');
var app = express();
app.get('/',function(req,res){
    res.send('Hello world');
});
app.listen(8080,function(){
    console.log("服务器启动了")
})
//结果:
服务器启动了
(点击web服务 会出现Hello world)

路由:

用于确定应用程序如何响应客户端请求,包含一个URI(路径)和一个特定的HTTP请求方法(GET,POST)

每个路由可以具有一个或者多个处理程序函数,这些函数在路由匹配时执行

app.method(path,handler)

注:app是express的实例,method是指HTTP请求方法(GET,POST等),path是指服务器上的路径,handle是指路由匹配时执行的函数

var express = require('express');
var app = express();
//GET请求
app.get('/',function(req,res){
    console.log("GET请求");
    res.end('Hello ,我是GET请求');
});
//POST请求
app.post('/',function(req,res){
    console.log("POST请求");
    res.end('Hello,我是POST请求')
})
//index响应index页面,我是GET请求
app.get('/index',function(req,res){
    console.log("响应index页面GET请求");
    res.end('Hello,我是index页面GET请求')
})
//对页面abcd ,abxcd,ab123cd,等响应GET请求
app.get('/ab*cd',function(req,res){
    console.log("/ab*cd GET请求");
    res.end('Hello,我是正则匹配')
})
app.listen(8080,function(){
    console.log("服务器启动了")
})

对比之前用的原生http,少了很多的判断语句,代码量大大减少,express框架对于Node.js就相当于jQuery和js

静态文件:

express提供了内置的中间件express.static来设置静态文件如:图片,css,js,比如:

//我们只有公开了public目录,才可以直接通过/public/xx的方式访问public目录中的资源

app.use('/public/',express.static('./public/'));

例子:新建一个public目录,目录下新建test.txt文件,里面随便写一句话,再在project目录下新建一个testStatic.js文件

var express = require('express');
var app = express();
app.use(express.static('public'));
app.get('/',function(req,res){
    res.end('Hello world')
})
app.listen(8080,function(){
    console.log("服务器启动了")
})
//web url后面输入test.txt,会显示里面的内容

Express框架处理GET请求和POST请求

GET请求

表单提交案例: 新建一个getTest.html文件  getTest.js文件

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <form action="/get_test" method="GET">
        学号:<input type="text" name="stuNum"> <br />
        姓名:<input type="text" name="stuNam">
        <input type="submit" value="提交">
        </form>
    </body>
</html>
var express=require('express');
var app = express();
app.get('/',function(req,res){
    //传送指定路径的文件  -会自动根据文件extension设定Content-Type
    //也可以用前面的art-template模板引擎
    res.sendFile(__dirname + "/" +"getTest.html");
})
app.get('/get_test',function(req,res){   //路由
    //输出JSON格式
    var response={
        'studentNumber':req.query.stuNum,
        'studentName':req.query.stuNam
    };
    console.log(response);
    //JSON.stringify()方法是将一个js值(对象或者数组)转换成一个JSON字符串
    res.end(JSON.stringify(response));
})
app.listen(8080,function(){
    console.log("服务器启动了");
})
//

POST请求:

新建一个postTest.html文件  postTest.js文件

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <form action="/post_test" method="POST">
        学号:<input type="text" name="stuNum"> <br />
        姓名:<input type="text" name="stuNam">
        <input type="submit" value="提交">
        </form>
    </body>
</html>
var express=require('express');
var app = express();
//加载body-parser
var bodyParser = require('body-parser');
//创建application/x-www-form-urlencoded编码解析
var urlencodedParser = bodyParser.urlencoded({extended:false})
app.get('/',function(req,res){
    //传送指定路径的文件  -会自动根据文件extension设定Content-Type
    //也可以用前面的art-template模板引擎
    res.sendFile(__dirname + "/" +"postTest.html");
})
app.post('/post_test',urlencodedParser,function(req,res){   //路由
    //输出JSON格式
    var response={
        'studentNumber':req.body.stuNum,
        'studentName':req.body.stuNam
    };
    console.log(response);
    //JSON.stringify()方法是将一个js值(对象或者数组)转换成一个JSON字符串
    res.end(JSON.stringify(response));
})
app.listen(8080,function(){
    console.log("服务器启动了");
})

创建一个简单的网站的例子:

用express框架改写前面的创建的例子.其中index.html和register.html的代码与前面一致

首先引入art-template模板引擎:

npm install express srt-template express-art-template

在project目录下建一个view目录,在view下面建index.html和register.html页面,新建一个app.js的文件代码:

var express = require('express');
var app = express();
app.engine('html',require('express-art-template'))

app.get('/', function (req, res) {
  res.render('index.html');
})

app.get('/register', function (req, res) {
   res.render('register.html');
})


app.listen(8080, function () {
  console.log("服务器启动了");
});

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: aspose.cells.rar 18.4.7 是一个文件压缩包,其中包含了 Aspose.Cells 的 18.4.7 版本的相关文件。Aspose.Cells 是一款强大的电子表格处理组件,可用于创建、读取、修改和保存 Excel 文件。 18.4.7 版本是 Aspose.Cells 的特定版本,其中包含了一些新功能、改进和 bug 修复。Aspose.Cells 可以通过该版本实现更好的性能和稳定性,提供更多的功能选项,提高用户体验。 该压缩包的 .rar 格式是一种常见的压缩文件格式,可以使用相应的解压软件将其解压缩。解压后,可以找到包含 Aspose.Cells 文件和示例代码的文件夹。 在使用 Aspose.Cells 18.4.7 进行开发时,需要将相应的 DLL 文件添加到项目引用中,并按照文档中的说明来调用和使用相应的 API。 Aspose.Cells 的功能非常强大,可以用于处理电子表格的各种操作,如读取和写入单元格数据、设置格式、合并拆分单元格、插入和删除行列、创建图表等。它还支持导入和导出各种文件格式,如 Excel、CSV、HTML 和 PDF。 总之,aspose.cells.rar 18.4.7 是 Aspose.Cells 特定版本的压缩文件,包含了相关文件和示例代码,通过使用这个版本,可以更好地利用 Aspose.Cells 的功能来进行电子表格处理和开发。 ### 回答2: aspose.cells.rar 18.4.7是一个文件压缩包,包含了Aspose.Cells 18.4.7版本的相关资源和文件。 Aspose.Cells是一个用于处理Excel文件的强大的Java组件。18.4.7代表了该组件的版本号,该版本是在2018年4月7日发布的。 这个压缩包中包含了Aspose.Cells库的所有相关的JAR文件,可以用于在Java项目中集成和使用Aspose.Cells的功能。通过引入这些JAR文件,开发者可以方便地操作Excel文件,如读取、写入、修改、格式化、计算、渲染等各种操作。 使用这个压缩包,开发人员可以轻松地在他们的Java应用程序中添加Excel文件的生成和处理功能。无论是在Windows、Linux还是其他支持Java运行环境的平台上,都可以使用Aspose.Cells来进行Excel文件的相关操作。 此外,Aspose.Cells还提供了丰富的API,例如可以操作单元格、行、列、工作表、图表等,也可以进行图像处理和数据导入导出等功能。这些功能可以帮助开发人员更好地处理和操作Excel文件,提高开发效率。 总之,aspose.cells.rar 18.4.7是包含Aspose.Cells 18.4.7版本相关资源和文件的压缩包,可以帮助开发人员在他们的Java项目中轻松使用和集成Aspose.Cells的功能。 ### 回答3: aspose.cells.rar 18.4.7是一个文件压缩包,其中包含了Aspose.Cells的版本18.4.7。Aspose.Cells是一个用于处理Excel文件的类库,提供了许多功能和工具来操作和操作Excel文件。 该压缩包中的内容主要是一些源代码文件、示例和文档。源代码文件是Aspose.Cells的核心库,它们包含了所有必要的类和方法来读取、修改和创建Excel文件。示例文件则展示了如何使用Aspose.Cells来解决各种常见的Excel处理任务,例如读取数据、设置格式和公式,以及生成图表等。而文档文件则是Aspose.Cells的用户指南和API文档,用于帮助开发者了解和使用该类库。 通过使用aspose.cells.rar 18.4.7,开发者可以方便地将Aspose.Cells集成到他们的应用程序中,从而实现Excel文件的各种操作。无论是在读取和分析数据,还是在将数据导出到Excel报表中,Aspose.Cells都提供了丰富的功能和灵活性。 总之,aspose.cells.rar 18.4.7是一个用于处理Excel文件的类库Aspose.Cells的压缩包,其中包含了源代码文件、示例和文档,开发者可以使用它来实现各种与Excel文件相关的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值