本文展示是基于node.js的静态文件服务器,代码参考自这里,主要是练习node http、文件模块的使用,另外,对理解http协议也很有帮助
除了实现了基本的路由控制,还实现了MIME类型、304缓存、gzip压缩、目录读取

首先是配置文件,setting.js

var setting = {
webroot : '/xxx/xxx/webroot',
viewdir : false,
index : 'index.html', //只有当viewdir为false时,此设置才有用
expires : {
filematch : /^(gif|png|jpg|js|css)$/ig,
maxAge: 60 * 60 //默认为一个月
},
compress : {
match : /css|js|html/ig
}
};
module.exports = setting;

MIME映射,mime.js

var mime = {
"html": "text/html",
"ico": "image/x-icon",
"css": "text/css",
"gif": "image/gif",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"js": "text/javascript",
"json": "application/json",
"pdf": "application/pdf",
"png": "image/png",
"svg": "image/svg+xml",
"swf": "application/x-shockwave-flash",
"tiff": "image/tiff",
"txt": "text/plain",
"wav": "audio/x-wav",
"wma": "audio/x-ms-wma",
"wmv": "video/x-ms-wmv",
"xml": "text/xml"
};
module.exports = mime;

然后是主程序,server.js

var http = require('http');
var setting = require('./setting.js');
var mime = require('./mime');
var url = require('url');
var util = require('util');
var path = require('path');
var fs = require('fs');
var zlib = require('zlib');
//访问统计
var number = 0;
var accesses = {};
 
http.createServer(function(req, res){
res.number = ++number;
accesses[res.number] = {startTime : new Date().getTime()};
var pathname = url.parse(req.url).pathname;
//安全问题,禁止父路径
pathname = pathname.replace(/\.\./g, '');
var realPath = setting.webroot + pathname;
accesses[res.number].path = pathname;
readPath(req, res, realPath, pathname);
}).listen(8000);
 
console.log('http server start at parth 8000\n\n\n');
//判断文件是否存在
function readPath(req, res, realPath, pathname){
//首先判断所请求的资源是否存在
path.exists(realPath, function(ex){
console.log('path.exists--%s', ex);
if(!ex){
responseWrite(res, 404, {'Content-Type' : 'text/plain'},
'This request URL ' + pathname + ' was not found on this server.');
}else{
//文件类型
fs.stat(realPath, function(err, stat){
if(err){
responseWrite(res, 500, err);
}else{
//目录
if(stat.isDirectory()){
//是否读取目录
if(setting.viewdir){
fs.readdir(realPath, function(err, files){
if(err){
responseWrite(res, 500, err);
}else{
var htm = '<html><head><title>' + pathname + '</title></head><body>' + pathname + '<hr>';
for(var i = 0; i < files.length; i++){
htm += '<br><a href="' + pathname + (pathname.slice(-1) != '/' ? '/' : '')
+ files[i] + '">' + files[i] + '</a>', 'utf8';
}
responseWrite(res, 200, {'Content-Type' : 'text/html'}, htm);
}
});
}else if(setting.index && realPath.indexOf(setting.index) < 0){
readPath(req, res, path.join(realPath, '/', setting.index), path.join(pathname, '/', setting.index));
}else{
responseWrite(res, 404, {'Content-Type' : 'text/plain'},
'This request URL ' + pathname + ' was not found on this server.');
}
}else{
var type = path.extname(realPath);
type = type ? type.slice(1) : 'nuknown';
var header = {'Content-Type' : mime[type] || 'text/plain'};
//缓存支持
if(setting.expires && setting.expires.filematch
&& type.match(setting.expires.filematch)){
var expires = new Date(),
maxAge = setting.expires.maxAge || 3600 * 30;
expires.setTime(expires.getTime() + maxAge * 1000);
header['Expires'] = expires.toUTCString();
header['Cache-Control'] = 'max-age=' + maxAge;
var lastModified = stat.mtime.toUTCString();
header['Last-Modified'] = lastModified;
//判断是否304
if(req.headers['if-modified-since'] && lastModified == req.headers['if-modified-since']){
responseWrite(res, 304, 'Not Modified');
}else{
readFile(req, res, realPath, header, type);
}
}else{
readFile(req, res, realPath, header, type);
}
}
}
});
}
});
}
//读文件/压缩/输出
function readFile(req, res, realPath, header, type){
var raw = fs.createReadStream(realPath), cFun;
//是否gzip
if(setting.compress && setting.compress.match
&& type.match(setting.compress.match) && req.headers['accept-encoding']){
if(req.headers['accept-encoding'].match(/\bgzip\b/)){
header['Content-Encoding'] = 'gzip';
cFun = 'createGzip';
}else if(req.headers['accept-encoding'].match(/\bdeflate\b/)){
header['Content-Encoding'] = 'deflate';
cFun = 'createDeflate';
}
}
res.writeHead(200, header);
if(cFun){
raw.pipe(zlib[cFun]()).pipe(res);
}else{
raw.pipe(res);
}
}
//普通输出
function responseWrite(res, starus, header, output, encoding){
encoding = encoding || 'utf8';
res.writeHead(starus, header);
if(output){
res.write(output, encoding);
}
res.end();
accesses[res.number].endTime = new Date().getTime();
//日志输出
console.log('access[%s]--%s--%s--%s--%s\n\n', res.number, accesses[res.number].path,
(accesses[res.number].endTime - accesses[res.number].startTime),
starus, (output ? output.length : 0));
delete accesses[res.number];
}

over!
尚欠缺的功能:日志记录、断点、容错等~~以后有时间再加啦

nodejs入门-静态文件服务器的更多相关文章

  1. 从零开始,在windows上用nodejs搭建一个静态文件服务器

    从零开始,在windows上用nodejs搭建一个静态文件服务器 首先安装nodejs: 新建一个node文件夹 下载node.exe到该文件夹 下载npm然后解压到该文件夹 现在node文件夹是这样 ...

  2. [转载]用NodeJS打造你的静态文件服务器

    http://www.open-open.com/bbs/view/1321344823593 本文是我对V5Node项目的总结,该项目的特性包括: 项目大多数的文件都是属于静态文件,只有数据部分存在 ...

  3. 转:nginx入门指南,快速搭建静态文件服务器和代理服务器

    本文介绍 Nginx 入门基础知识,让你迅速搭建 Nginx 服务器.主要内容包括 Nginx 安装和简单使用.Nginx的简单原理.Nginx 配置文件的结构.如何使用 Nginx 来提供静态文件服 ...

  4. 我的前端之旅-nodejs 安装静态的文件服务器 (1)

    一个最简单的 Web Server 之功能包含下列三个步骤:步骤一 : 接收浏览器所传来的网址:步骤二 : 取出相对应的文件:步骤三 : 将文件内容传回给浏览器.然而.在这个接收与传回的过程中,所有的 ...

  5. Node.js静态文件服务器实战[转]

    p.s. 在下面这篇文章的指导下,做了一个静态文件服务器,见:https://github.com/walkerwzy/node_static_server ==== 这是一篇阐述得比较详细的文章,从 ...

  6. Anywhere 随启随用的静态文件服务器

    三江建材官网项目 写nodeJs系列的文章都是因为这一个项目 第一天,搭建项目环境 记录心情: 首先,在写这个项目的时候,我很无助,只是拿到了设计稿,还有一个指导人,平常会很忙,只有在休闲的时候才能动 ...

  7. nodeJs 5.0.0 安装配置与nodeJs入门例子学习

    新手学习笔记,高手请自动略过 安装可以先看这篇:http://blog.csdn.net/bushizhuanjia/article/details/7915017 1.首先到官网去下载exe,或者m ...

  8. NodeJS入门(四)—— path对象

    很快Node就会迎来4.0的时代,届时将并入现有的iojs,所以先前写过的iojs入门系列直接更名为NodeJS入门. 本篇开始将逐个介绍Node的各主要模块,依循API文档走一遍,但会给出比API文 ...

  9. nodejs express 静态文件的路径

    当express 设置为静态文件服务器的时候.可以通过2种方式进行方位: 1,通过设置app.use('路径1','../a/b/image') express 路径的形式,如 src="路 ...

随机推荐

  1. The.first.glance.at.linux.commands

    ## Get Ubuntu Version Info lsb_release -a ## Get Linux kernal info uname -a ## Get Computer name ech ...

  2. 第二百三十五节,Bootstrap栅格系统

    Bootstrap栅格系统 学习要点: 1.移动设备优先 2.布局容器 3.栅格系统 本节课我们主要学习一下 Bootstrap 的栅格系统,提供了一套响应式.移动设备优先的流 式栅格系统. 一.移动 ...

  3. oracledbconsole db启动问题

    oracledbconsole db启动问题 被这个OracleDBconsole服务无法启动的问题折磨了两个星期了,今天很幸运,在网上无意间看到了一位大侠的思路,虽然错误的情况并不完全相同,但他的思 ...

  4. 【转】VC++的Unicode编程

    转自http://www.cnblogs.com/kex1n/archive/2010/03/15/2286510.html 原始出处http://www.vckbase.com/document/v ...

  5. linux more less cat

    在使用和维护Linux系统时,常常需要查看文件的相关内容,那么如何才能做到呢?下面小编就以CentOS6.4系统为例演示查看文件内容的几种常用的方法. 工具/原料   CentOS6.4 查看文件内容 ...

  6. 客户端用JavaScript填充DropDownList控件 服务器端读不到值

    填充没有任何问题,但是在服务器端却取不出来下拉表中的内容.页面代码如下. <form id="form1" runat="server"> < ...

  7. MANIFEST.MF 文件内容完全详解

    http://blog.csdn.net/zhifeiyu2008/article/details/8829637

  8. WebSocket入门教程(五)-- WebSocket实例:简单多人聊天室

    from:https://blog.csdn.net/u010136741/article/details/51612594 [总目录]   WebSocket入门教程--大纲   [实例简介]   ...

  9. iOS Search bar 输入空字符串也可以搜索

    Search bar delegate - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { UITextField *sea ...

  10. iOS 如何用JSONKit读写JSON文件

     如何用JSONKit读写JSON文件 分类: ios2013-04-20 12:46 510人阅读 评论(0) 收藏 举报 JSON文件格式简单,使用方便,值得一用. 目前已经有多个库支持Json文 ...