Node. js development-HTTP file server,
The HelloWorld example is only for demonstration purposes. Here is an actual example: file server. We use Node. js to create an HTTP File Server. You can use a browser or other download tool to download files to the file server.
The HTTP file server implemented by Node. js isQt Network Programming Practice-HTTP ServerThe version implemented using Qt in video courses is much less complex.
To read files, we will use the File System module (named "fs") and Stream. We also need to analyze the URL, distinguish the HTTP method, and use EventEmitter.
FileServer code of the file server
The code is still simple:
// Introduce the http module var http = require ("http"); var fs = require ("fs"); // create a server and specify the function http for processing client requests. createServer (function (request, response) {// judge the HTTP method and only process GET if (request. method! = "GET") {response. writeHead (403); response. end (); return null;} // The URL module can also be used here to analyze URL (https://nodejs.org/api/url.html) var sep = request. url. indexOf ('? '); Var filePath = sep <0? Request. url: request. url. slice (0, sep); console. log ("GET file:" + filePath); // send data to the client when the file exists; otherwise, 404 var fileStat = fs. stat (". "+ filePath, function (err, stats) {if (err) {response. writeHead (404); response. end (); return null;} // TODO: Content-Type set response according to the file Type. writehead( 200, {"Content-Type": "text/plain", "Content-Length": stats. size}); // use Stream var stream = fs. createReadStream (". "+ filePath); stream. on ('data', function (chunk) {response. write (chunk) ;}); stream. on ('end', function () {response. end () ;}); stream. on ('error', function () {response. end ();});});}). listen (8000); console. log ("Hello World start listen on port 8000 ");
The biggest change is the parameter passed to the createServer method.
We made a judgment based on request. method. If it is not GET, 403 is returned. If yes, check whether the file exists and does not exist. If 404 is returned, read the data to the client. The logic is so simple. Next we will introduce the new knowledge used.
File System
To use FileSystem, use require to introduce the fs module, as in the previous code. The API of File System is old, so let's take a look at it: https://nodejs.org/api/fs.html. We only talk about the features used.
Get File status
In our FileServer, the file status is obtained through the fs. stat () method when receiving a request from the client. The prototype of the fs. stat () method is as follows:
fs.stat(path, callback)
The first parameter is the file path, and the second parameter is the callback function. The fs. stat () method is asynchronous and the result is returned through the callback function callback. The callback prototype is as follows:
function(err, stats)
The first parameter indicates whether an error has occurred. The second parameter is an object of the fs. Stats type and stores the File status information, such as the size, Creation Time, and modification time.
After the FileServer code obtains the File status, it reads the size, calls the writeHead method of http. ServerResponse, sets the HTTP status code to 200, and sets the Content-Length header. The Code is as follows:
response.writeHead(200, {"Content-Type": "text/plain", "Content-Length": stats.size})
ReadStream
Next, we call fs. createReadStream to create a ReadStream object. ReadStream is Stream and EventEmitter.
The prototype of fs. createReadStream is as follows:
fs.createReadStream(path[, options])
The first parameter is the file path, and the second parameter is an optional JSON object, which is used to specify some options for opening the file. The default value is as follows:
{Flags: 'R ',
Encoding: null,
Fd: null,
Mode: 0666,
AutoClose: true
}
The default autoClose attribute is true. When an error occurs during file reading or reading, the file is automatically closed. The fd attribute can be associated with an existing file descriptor, which will ignore the path and create a stream based on an opened file. Options can also have the start and end items, specifying the start and end locations and reading specific areas of the file. This is required if we want to implement resumable data transfer. The usage is similar to this:
fs.createReadStream('sample.mp4', {start: 1000, end: 10000});
Encoding is used to specify the file encoding, which has special significance for text files. Currently, 'utf8', 'ascii ', and 'base64' are supported '.
ReadStream reads data asynchronously. When reading a part, it sends a data event. The data is passed to the listener (actually a callback method) associated with the event ). In our code, we only call response. write to write data to the client. Note: multiple calls may be made to response. write. Because we have set Content-Length, the chunked encoding method is not used. If Content-Length is not set, the chunked mode is enabled by default.
ReadStream will launch an end event when reading the file and an error event when an error occurs. We listen to these two events and simply terminate the response.
We can see the stream. on code in the sample code. Let's explain it below.
EventEmitter
Node. js's event-driven IO Based on the V8 engine is one of its biggest and best features. With the event mechanism, we can make full use of asynchronous IO to break through the performance bottleneck of the single-Thread Programming Model, making it of practical significance to use JavaScript For backend development.
Basic EventEmitter usage
Events. eventEmitter is a simple implementation of event transmitters. It has addListener, on, once, removeListener, emit, and other methods. developers can conveniently call these APIs to listen to an event or launch an event.
The fs. ReadStream we use in this example is an EventEmitter, which implements the stream. Readable interface, and stream. Readable has data, error, end, close, readable and other events.
Generally, we use the on or addListener of EventEmitter to listen to an event. This time may be triggered multiple times. Each time it is triggered, the callback method we provide will be called. The code in our example is as follows:
stream.on('data',function(chunk){ response.write(chunk); });
The Node. js event mechanism associates a callback method list for an event, so that multiple listeners can listen to the same event. Each event may be transmitted with data and status, which are passed through callback parameters. The parameter of the callback method corresponding to a specific event is determined by the class (Instance) defined by the event. The emit method prototype of EventEmitter is as follows:
emitter.emit(event[, arg1][, arg2][, ...])
This prototype indicates that the callback method of an event can have one or more parameters or have no parameters. If you want to know whether the callback method of an event has parameters and the meaning of each parameter, you have to go to the relevant API documentation. The parameter of stream. Readable data event is chunk, Buffer type, representing read data.
If you only want to listen to an event once, you can call the once method of EventEmitter. To remove an event listener, call removeListener. To remove all listeners, call removeAllListener.
Custom events
Many modules of Node. js inherit from the Event module. We can also inherit EventEmitter to implement our own objects and add our own custom events.
Here is a simple example:
var util=require("util");var events = require("events");function Ticker() { var self = this; events.EventEmitter.call(this); setInterval(function(){ self.emit("tick") }, 1000 );}util.inherits(Ticker, events.EventEmitter);var ticker = new Ticker();ticker.on("tick", function() { console.log("tick event");});
In this simple example, we define a Ticker object and use the global setInterval method to enable a timer to send an event named "tick" every 1000 milliseconds.
The tool module of Node. js encapsulates the inherited methods. We call the inherits method to inherit events. EventEmitter from Ticker.
The usage of custom events is exactly the same as that provided by the Node. js built-in module.
Other articles:
- Getting started with Node. js Development -- HelloWorld Analysis
- Node. js development entry-Environment setup and HelloWorld
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.