1. Opening analysis
The file system module is a simple packaged set of standard POSIX file I/O operation methods. The module can be obtained by calling require("fs"). All methods in the file system module are available in asynchronous and synchronous versions.
(1) The asynchronous method in the file system module requires a completed callback function as the last incoming formal parameter.
(2) The composition of the callback function is determined by the asynchronous method called. Generally, the first formal parameter of the callback function is the returned error message.
(3) If the asynchronous operation is executed correctly and returns, the error formal parameter is null or undefined. If you are using the synchronous version of the operation method, once an error occurs, an error will be returned in the usual form of throwing an error.
(4) You can use try and catch statements to intercept errors and make the program continue.
Let's first look at a simple example, read the file ("bb.txt"):
(1) Create the file "bb.txt", as follows ("Hello everyone, I am Nobita! (*^__^*) Hehe...").
(2), read the file operation as follows:
The code copy is as follows:
var fs = require("fs");
fs.readFile("bb.txt","utf8",function (error,data){
if(error) throw error ;
console.log(data);
}) ;
Running results:
What you need to note here is: you must set the encoding when reading files, otherwise the default form will appear in "buffer".
Looking at the running effect that is not set, the difference is still very obvious. as follows:
Another write operation, as follows:
The code copy is as follows:
var fs = require("fs");
var txt = "Everyone should learn NodeJS!!!" ;
//Write to file
fs.writeFile("bb.txt",txt,function (err) {
if (err) throw err ;
console.log("File Saved !"); //The file is saved
}) ;
Running results:
Here are some common examples:
The code copy is as follows:
// Delete the file
fs.unlink('bb.txt', function(){
console.log('success');
}) ;
// Modify the file name
fs.rename('bb.txt','bigbear.txt',function(err){
console.log('rename success');
});
// Check file status
fs.stat('bb.txt', function(err, stat){
console.log(stat);
});
// Determine whether the file exists
fs.exists('bb.txt', function( exists ){
console.log( exists );
}) ;
2. The connection between Fs and Stream
"Stream" has asynchronous features. Can I divide a file or a piece of content into unknown "chunks" and read it, and every time a "chunk" is read, we output it. Until the file is finished. This is like "Transfer-Encoding: chunked" supported by "http1.1". ("chunk" can exist in any form, NodeJS exists in the form of "Buffer" by default, which is more efficient). "Stream" in NodeJS has a super feature on Unix systems, which is ("pipe" ------ pipeline).
Do you still remember the first NodeJS program "Hello, Big Bear!"? We make some modifications based on the applet, as follows:
(1), create "bb.html"
The code copy is as follows:
<html>
<head>
<style type="text/css">
div {
margin-top: 50px;
width: 100%;
margin: 0px;
height:120px;
line-height:120px;
color:#ffff;
font-size:22px;
background:#ff9900;
text-align: center;
}
</style>
</head>
<body>
<div>Hello, Big Bear! </div>
</body>
</html>
(2), modify the previous program as follows:
The code copy is as follows:
var http = require('http') ;
var fs = require("fs");
var server = http.createServer(function(req,res){
fs.readFile("bb.html","utf-8", function(err, data){
if(err) {
res.writeHead(500, {'Context-Type': 'text/plain'});
res.end('specify file not exists! or server error!');
}
else{
res.writeHead(200, {'Context-Type': 'text/html'});
res.write(data);
res.end();
}
})
}) ;
server.listen(8888);
console.log("http server running on port 8888...") ;
The following are the running results:
Now we need to think about it, if we are sending not a simple text file but a hypermedia file, such as the full HD video file of Google 2014 IO Conference. mp4 format. Length is over 2 hours 1080p.
About 4 GB. The way "readFile" is known to work is to read files into memory. Then such a large file obviously cannot be done. So what should I do? After that, you need to use stream to do it. So that's it.
The code is as follows:
The code copy is as follows:
fs.createReadStream(__dirname + '/vedio.mp4').pipe(res) ;
To summarize:
These codes can implement the required functions, but the service needs to cache the entire file data to memory before sending the file data, if the "bb.html" file is very
If it is large and has a large concurrency, a lot of memory will be wasted. Because the user needs to wait until the entire file is cached to memory to accept the file data, this leads to
The user experience is quite bad. Fortunately, both parameters "(req, res)" are Stream, so we can use fs.createReadStream() instead of "fs.readFile()".
Three, examples
Come to upload a file:
(1) Create "server.js"
The code copy is as follows:
var http = require('http');
var url = require('url');
function start(route, handler) {
function onRequest (request, response) {
var pathname = url.parse(request.url).pathname;
//Route to the corresponding business logic
route (pathname, handler, response, request);
}
http.createServer(onRequest).listen(3000);
console.log('server is starting');
}
exports.start = start;
(2) Create "route.js"
The code copy is as follows:
function route (pathname, handler, response, request) {
console.log('about to route a request for ' + pathname);
if (typeof handler[pathname] === 'function') {
return handler[pathname](response, request);
} else {
console.log('no request handler found for ' + pathname);
response.writeHead(404, {'Content-Type': 'text/html'});
response.write('404 Not Found!');
response.end();
}
}
exports.route = route;
(3) Create "requestHandler.js"
The code copy is as follows:
var querystring = require('querystring'),
fs = require('fs'),
formidable = require('formidable');
function start (response, request) {
console.log('start module');
var body = '<html>'+
'<head>'+
'<meta http-equiv="Content-Type" '+
'content="text/html; charset=UTF-8" />'+
'</head>'+
'<body>'+
'<form action="/upload" enctype="multipart/form-data" method="post">'+
'<input type="file" name="upload" multiple="multiple">'+
'<input type="submit" value="Submit text" />'+
'</form>'+
'</body>'+
'</html>';
response.writeHead(200, {'Content-Type': 'text/html'});
response.write(body);
response.end();
}
function upload (response, request) {
console.log('upload module');
var form = new formidable.IncomingForm();
form.parse(request, function (error, fields, files) {
fs.renameSync(files.upload.path, '/tmp/test.png');
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('You/'ve sent: <br />');
response.write('<img src="/show" />');
response.end();
});
}
function show (response, request) {
console.log('show module');
fs.readFile ('/tmp/test.png', 'binary', function (error, file) {
if (error) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.write(error);
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;
(4), create "index.js"
The code copy is as follows:
var server = require('./server');
var router = require('./router');
var requestHandler = require('./requestHandler');
var formidable = require('formidable'); // require path search algorithm? ?
var handler = {};
handler['/'] = requestHandler.start;
handler['/start'] = requestHandler.start;
handler['/upload'] = requestHandler.upload;
handler['/show'] = requestHandler.show;
server.start(router.route, handler);
Four, let's summarize
(1) Understand the "connection between Fs and Stream".
(2) Proficient in using "FS"-related APIs.
(3) Pay attention to the details, such as: the processing details between the file operation API synchronization method and the asynchronous method.
(4), and finally emphasize: understand the code organization method in file upload examples, constantly refactor, and constantly summarize.