当前位置: 代码迷 >> JavaScript >> 基于Node.js的容易文件服务器
  详细解决方案

基于Node.js的容易文件服务器

热度:393   发布时间:2012-10-28 09:54:44.0
基于Node.js的简单文件服务器
最近看了下Node.js,基于V8的服务端javascript,有点意思,就写了个简单的文件夹系统,用于列出系统的某个文件夹下的文件,并可以实现下载。不过对于比较大的文件,可能会有点问题。。Node.js一般在linux下运行,附件是基于cygwin的版本,可以测试下 ,运行方式为node filesystem.js。cygwin版本的node.js有人已经上传了,见地址http://dl.iteye.com/topics/download/996e51ce-7489-3dfe-a38b-01ee2a7c4d9d




贴下代码:
/***
 * @author flyingzl
 * @date 2010-11-27
 * 一个基于Node.js的简单文件服务器
 */

var fs=require("fs"),
	http=require("http"),
	url=require("url"),
	path=require("path"),
	mime=require("./mime").mime,
	util=require('util');

//www根目录
var root=__dirname,
	host="127.0.0.1",
	port="8888";
	
	
if(!path.existsSync(root)){
	util.error(root+"文件夹不存在,请重新制定根文件夹!");
	process.exit();
}
	
//显示文件夹下面的文件
function listDirectory(parentDirectory,req,res){
	fs.readdir(parentDirectory,function(error,files){
		var body=formatBody(parentDirectory,files);
		res.writeHead(200,{
			"Content-Type":"text/html;charset=utf-8",
			"Content-Length":Buffer.byteLength(body,'utf8'),
			"Server":"NodeJs("+process.version+")"
		});
		res.write(body,'utf8');
		res.end();
	});

}

//显示文件内容
function showFile(file,req,res){
	fs.readFile(filename,'binary',function(err,file){
		var contentType=mime.lookupExtension(path.extname(filename));
		res.writeHead(200,{
			"Content-Type":contentType,
			"Content-Length":Buffer.byteLength(file,'binary'),
			"Server":"NodeJs("+process.version+")"
		});
		res.write(file,"binary");
		res.end();
	})
}

//在Web页面上显示文件列表,格式为<ul><li></li><li></li></ul>
function formatBody(parent,files){
	var res=[],
		length=files.length;
	res.push("<!doctype>");
	res.push("<html>");
	res.push("<head>");
	res.push("<meta http-equiv='Content-Type' content='text/html;charset=utf-8'></meta>")
	res.push("<title>Node.js文件服务器</title>");
	res.push("</head>");
	res.push("<body width='100%'>");
	res.push("<ul>")
	files.forEach(function(val,index){
		var stat=fs.statSync(path.join(parent,val));
		if(stat.isDirectory(val)){
			val=path.basename(val)+"/";
		}else{
			val=path.basename(val);
		}
		res.push("<li><a href='"+val+"'>"+val+"</a></li>");
	});
	res.push("</ul>");
	res.push("<div style='position:relative;width:98%;bottom:5px;height:25px;background:gray'>");
	res.push("<div style='margin:0 auto;height:100%;line-height:25px;text-align:center'>Powered By Node.js</div>");
	res.push("</div>")
	res.push("</body>");
	return res.join("");
}

//如果文件找不到,显示404错误
function write404(req,res){
	var body="文件不存在:-(";
	res.writeHead(404,{
		"Content-Type":"text/html;charset=utf-8",
		"Content-Length":Buffer.byteLength(body,'utf8'),
		"Server":"NodeJs("+process.version+")"
	});
	res.write(body);
	res.end();
}

//创建服务器
http.createServer(function(req,res){
	//将url地址的中的%20替换为空格,不然Node.js找不到文件
	var pathname=url.parse(req.url).pathname.replace(/%20/g,' '),
		re=/(%[0-9A-Fa-f]{2}){3}/g;
	//能够正确显示中文,将三字节的字符转换为utf-8编码
	pathname=pathname.replace(re,function(word){
		var buffer=new Buffer(3),
			array=word.split('%');
		array.splice(0,1);
		array.forEach(function(val,index){
			buffer[index]=parseInt('0x'+val,16);
		});
		return buffer.toString('utf8');
	});
	if(pathname=='/'){
		listDirectory(root,req,res);
	}else{
		filename=path.join(root,pathname);
		path.exists(filename,function(exists){
			if(!exists){
				util.error('找不到文件'+filename);
				write404(req,res);
			}else{
				fs.stat(filename,function(err,stat){
					if(stat.isFile()){
						showFile(filename,req,res);
					}else if(stat.isDirectory()){
						listDirectory(filename,req,res);
					}
				});
			}
		});
	}
	
	
}).listen(port,host);

util.debug("服务器开始运行 http://"+host+":"+port)




接下来是mime.js,一个用于显示文件类型的js文件
var mime = {

  //查找文件后缀类型
  lookupExtension : function(ext, fallback) {
    return mime.TYPES[ext.toLowerCase()] || fallback || 'text/plain';
  },

  //文件类型
  TYPES : { ".3gp"   : "video/3gpp"
          , ".a"     : "application/octet-stream"
          , ".ai"    : "application/postscript"
          , ".aif"   : "audio/x-aiff"
          , ".aiff"  : "audio/x-aiff"
          , ".asc"   : "application/pgp-signature"
          , ".asf"   : "video/x-ms-asf"
          , ".asm"   : "text/x-asm"
          , ".asx"   : "video/x-ms-asf"
          , ".atom"  : "application/atom+xml"
          , ".au"    : "audio/basic"
          , ".avi"   : "video/x-msvideo"
          , ".bat"   : "application/x-msdownload"
          , ".bin"   : "application/octet-stream"
          , ".bmp"   : "image/bmp"
          , ".bz2"   : "application/x-bzip2"
          , ".c"     : "text/x-c"
          , ".cab"   : "application/vnd.ms-cab-compressed"
          , ".cc"    : "text/x-c"
          , ".chm"   : "application/vnd.ms-htmlhelp"
          , ".class"   : "application/octet-stream"
          , ".com"   : "application/x-msdownload"
          , ".conf"  : "text/plain"
          , ".cpp"   : "text/x-c"
          , ".crt"   : "application/x-x509-ca-cert"
          , ".css"   : "text/css"
          , ".csv"   : "text/csv"
          , ".cxx"   : "text/x-c"
          , ".deb"   : "application/x-debian-package"
          , ".der"   : "application/x-x509-ca-cert"
          , ".diff"  : "text/x-diff"
          , ".djv"   : "image/vnd.djvu"
          , ".djvu"  : "image/vnd.djvu"
          , ".dll"   : "application/x-msdownload"
          , ".dmg"   : "application/octet-stream"
          , ".doc"   : "application/msword"
          , ".dot"   : "application/msword"
          , ".dtd"   : "application/xml-dtd"
          , ".dvi"   : "application/x-dvi"
          , ".ear"   : "application/java-archive"
          , ".eml"   : "message/rfc822"
          , ".eps"   : "application/postscript"
          , ".exe"   : "application/x-msdownload"
          , ".f"     : "text/x-fortran"
          , ".f77"   : "text/x-fortran"
          , ".f90"   : "text/x-fortran"
          , ".flv"   : "video/x-flv"
          , ".for"   : "text/x-fortran"
          , ".gem"   : "application/octet-stream"
          , ".gemspec" : "text/x-script.ruby"
          , ".gif"   : "image/gif"
          , ".gz"    : "application/x-gzip"
          , ".h"     : "text/x-c"
          , ".hh"    : "text/x-c"
          , ".htm"   : "text/html"
          , ".html"  : "text/html"
          , ".ico"   : "image/vnd.microsoft.icon"
          , ".ics"   : "text/calendar"
          , ".ifb"   : "text/calendar"
          , ".iso"   : "application/octet-stream"
          , ".jar"   : "application/java-archive"
          , ".java"  : "text/x-java-source"
          , ".jnlp"  : "application/x-java-jnlp-file"
          , ".jpeg"  : "image/jpeg"
          , ".jpg"   : "image/jpeg"
          , ".js"    : "application/javascript;charset=utf-8"
          , ".json"  : "application/json"
          , ".log"   : "text/plain;charset=utf-8"
          , ".m3u"   : "audio/x-mpegurl"
          , ".m4v"   : "video/mp4"
          , ".man"   : "text/troff"
          , ".mathml"  : "application/mathml+xml"
          , ".mbox"  : "application/mbox"
          , ".mdoc"  : "text/troff"
          , ".me"    : "text/troff"
          , ".mid"   : "audio/midi"
          , ".midi"  : "audio/midi"
          , ".mime"  : "message/rfc822"
          , ".mml"   : "application/mathml+xml"
          , ".mng"   : "video/x-mng"
          , ".mov"   : "video/quicktime"
          , ".mp3"   : "audio/mpeg"
          , ".mp4"   : "video/mp4"
          , ".mp4v"  : "video/mp4"
          , ".mpeg"  : "video/mpeg"
          , ".mpg"   : "video/mpeg"
          , ".ms"    : "text/troff"
          , ".msi"   : "application/x-msdownload"
          , ".odp"   : "application/vnd.oasis.opendocument.presentation"
          , ".ods"   : "application/vnd.oasis.opendocument.spreadsheet"
          , ".odt"   : "application/vnd.oasis.opendocument.text"
          , ".ogg"   : "application/ogg"
          , ".p"     : "text/x-pascal"
          , ".pas"   : "text/x-pascal"
          , ".pbm"   : "image/x-portable-bitmap"
          , ".pdf"   : "application/pdf"
          , ".pem"   : "application/x-x509-ca-cert"
          , ".pgm"   : "image/x-portable-graymap"
          , ".pgp"   : "application/pgp-encrypted"
          , ".pkg"   : "application/octet-stream"
          , ".pl"    : "text/x-script.perl"
          , ".pm"    : "text/x-script.perl-module"
          , ".png"   : "image/png"
          , ".pnm"   : "image/x-portable-anymap"
          , ".ppm"   : "image/x-portable-pixmap"
          , ".pps"   : "application/vnd.ms-powerpoint"
          , ".ppt"   : "application/vnd.ms-powerpoint"
          , ".ps"    : "application/postscript"
          , ".psd"   : "image/vnd.adobe.photoshop"
          , ".py"    : "text/x-script.python"
          , ".qt"    : "video/quicktime"
          , ".ra"    : "audio/x-pn-realaudio"
          , ".rake"  : "text/x-script.ruby"
          , ".ram"   : "audio/x-pn-realaudio"
          , ".rar"   : "application/x-rar-compressed"
          , ".rb"    : "text/x-script.ruby"
          , ".rdf"   : "application/rdf+xml"
          , ".roff"  : "text/troff"
          , ".rpm"   : "application/x-redhat-package-manager"
          , ".rss"   : "application/rss+xml"
          , ".rtf"   : "application/rtf"
          , ".ru"    : "text/x-script.ruby"
          , ".s"     : "text/x-asm"
          , ".sgm"   : "text/sgml"
          , ".sgml"  : "text/sgml"
          , ".sh"    : "application/x-sh"
          , ".sig"   : "application/pgp-signature"
          , ".snd"   : "audio/basic"
          , ".so"    : "application/octet-stream"
          , ".svg"   : "image/svg+xml"
          , ".svgz"  : "image/svg+xml"
          , ".swf"   : "application/x-shockwave-flash"
          , ".t"     : "text/troff"
          , ".tar"   : "application/x-tar"
          , ".tbz"   : "application/x-bzip-compressed-tar"
          , ".tcl"   : "application/x-tcl"
          , ".tex"   : "application/x-tex"
          , ".texi"  : "application/x-texinfo"
          , ".texinfo" : "application/x-texinfo"
          , ".text"  : "text/plain"
          , ".tif"   : "image/tiff"
          , ".tiff"  : "image/tiff"
          , ".torrent" : "application/x-bittorrent"
          , ".tr"    : "text/troff"
          , ".txt"   : "text/plain"
          , ".vcf"   : "text/x-vcard"
          , ".vcs"   : "text/x-vcalendar"
          , ".vrml"  : "model/vrml"
          , ".war"   : "application/java-archive"
          , ".wav"   : "audio/x-wav"
          , ".wma"   : "audio/x-ms-wma"
          , ".wmv"   : "video/x-ms-wmv"
          , ".wmx"   : "video/x-ms-wmx"
          , ".wrl"   : "model/vrml"
          , ".wsdl"  : "application/wsdl+xml"
          , ".xbm"   : "image/x-xbitmap"
          , ".xhtml"   : "application/xhtml+xml"
          , ".xls"   : "application/vnd.ms-excel"
          , ".xml"   : "application/xml"
          , ".xpm"   : "image/x-xpixmap"
          , ".xsl"   : "application/xml"
          , ".xslt"  : "application/xslt+xml"
          , ".yaml"  : "text/yaml"
          , ".yml"   : "text/yaml"
          , ".zip"   : "application/zip"
          }
};

exports.mime=mime;

1 楼 oceandeep 2010-11-29  
最近想关注一下,看了楼主的代码 算是有所了解了
2 楼 aaxron 2010-12-01  
作为程序员,看见一大堆JS的嵌套写法.及JS语法的随性性.就头痛.
后续代码如何维护?

不过,还是很有创意

但相比传统的服务端,Node.JS有什么优势?




3 楼 vb2005xu 2010-12-01  
靠 根本就下载不到 还要注册 你放到javaeye会咋的啊???? 照说也就几个js文件 你直接贴出来不就得了,还污蔑javaeye不好用 我就觉得博客园不咋的
4 楼 superobin 2010-12-01  
aaxron 写道
作为程序员,看见一大堆JS的嵌套写法.及JS语法的随性性.就头痛.
后续代码如何维护?

不过,还是很有创意

但相比传统的服务端,Node.JS有什么优势?


JS那种写法是有点乱,关键是他那种闭包的写法可能乍一看让人比较头疼(但是开发功能的时候很舒服,穿透作用域这种事情实在太棒了O(∩_∩)O)。
Node.js是可以关注一下的,和ngnix一样的单线程事件模式,抗高压(但是需要保证这单一线程不崩溃。还好js中有try catch)。我曾经测试过10000个并发空闲连接占用50MB内存。现在国外这个的扩展很多,比如expressjs,专门用于web开发

另外,楼上想要楼主贴代码的话,,其实代码在上面贴着了,不过光有代码没有nodejs的服务端还是不行的吧。楼主附件贴的应该是服务端
5 楼 antipro 2010-12-01  
我也在关注nodejs,就是感觉js做服务器端还是挺有意思的。
6 楼 lgzjw 2010-12-01  
好像node.js不支持win系统
7 楼 jamiesun 2010-12-01  
我觉得代码挺好,哪里很乱。

8 楼 yy77 2010-12-01  
nodejs有windows下的编译版本啊。虽然不知道负载如何,但是开发开发还是完全没有问题的。

写起来还是有点难度的,因为不是传统的模式。
9 楼 flyingzl 2010-12-02  
vb2005xu 写道
靠 根本就下载不到 还要注册 你放到javaeye会咋的啊???? 照说也就几个js文件 你直接贴出来不就得了,还污蔑javaeye不好用 我就觉得博客园不咋的


今天我才知道博客园那边下载需要注册,不好意思了。不过,我的代码都已经贴出来了,就这两个文件,不知你是否测试过,或者是你否关注、了解过node.js?
10 楼 flyingzl 2010-12-02  
superobin 写道
aaxron 写道
作为程序员,看见一大堆JS的嵌套写法.及JS语法的随性性.就头痛.
后续代码如何维护?

不过,还是很有创意

但相比传统的服务端,Node.JS有什么优势?


JS那种写法是有点乱,关键是他那种闭包的写法可能乍一看让人比较头疼(但是开发功能的时候很舒服,穿透作用域这种事情实在太棒了O(∩_∩)O)。
Node.js是可以关注一下的,和ngnix一样的单线程事件模式,抗高压(但是需要保证这单一线程不崩溃。还好js中有try catch)。我曾经测试过10000个并发空闲连接占用50MB内存。现在国外这个的扩展很多,比如expressjs,专门用于web开发

另外,楼上想要楼主贴代码的话,,其实代码在上面贴着了,不过光有代码没有nodejs的服务端还是不行的吧。楼主附件贴的应该是服务端



是的。就是node.js的cygwin版,不过当时上传到javaeye速度实在太慢了,就上传到了博客园。哪里知道那边下载还需要登入,这个就是我的过错了。。哈。
11 楼 ray_linn 2010-12-02  
文件服务器???拜托,回去看看书本什么叫文件服务器,顶多就是个file explorer而已。
12 楼 flyingzl 2010-12-02  
ray_linn 写道
文件服务器???拜托,回去看看书本什么叫文件服务器,顶多就是个file explorer而已。


哥们,说话别这么冲,我都说了是个简单的文件服务器,不是你想的那种fs(就算是fs,它也有文件浏览、下载的功能)等。我只是当做是学习。。r。。。我们是重在交流技术,共同进步,而不是在这里说些毫无干系的话。
13 楼 matyhtf 2010-12-02  
node.js确实很独特,很有创意。
搞前端的人可以学习一下啊,挺有意思的。社区很活跃,各类第三方扩展五花八门的。
14 楼 superobin 2010-12-03  
呵呵。。我的博客里有一点之前写的烂代码,不过还是比较有趣的
15 楼 tapestry1122 2010-12-03  
plurk已经用nodejs替换掉了原来用netty3写的服务

他们大概是20w+的connection

用nodejs后,cpu稍微上升了一点,但是内存是大大的降低了
16 楼 lgzjw 2010-12-04  
为什么我官网上没看到支持win32系统的node。js啊
17 楼 flyingzl 2010-12-05  
lgzjw 写道
为什么我官网上没看到支持win32系统的node。js啊


node.js本来就是在linux下运行的,不过可以通过cgywin编译成win32版本的
18 楼 dopic 2010-12-06  
js代码怎么说呢, 很不错
19 楼 qgymje 2010-12-06  
很棒,我只运行过官网上的例子
20 楼 weskycn 2010-12-08  
ray_linn 写道
文件服务器???拜托,回去看看书本什么叫文件服务器,顶多就是个file explorer而已。


例子写的挺好的阿,只是个例子而已阿。重在展示
  相关解决方案