1
+ //需要注意的全局变量;
2
+
3
+ //网站的端口号
4
+ var port = 80 ;
5
+
6
+ //根目录
7
+ var basePath = "/home/w" ;
8
+ //var basePath = "E:/GitHub/nodejs-http-server.git/trunk";
9
+
10
+ //html主页路径
11
+ var index_file_path = basePath + "/main.html" ;
12
+
13
+ //日志文件路径
14
+ var log_file_path = basePath + "/log.txt" ;
15
+
16
+ //索引html的head区域的文件内容,指向的文件,这是相对路径;
17
+ var _INDEX_HEAD_FILE_NAME = "index_head.html" ;
18
+
19
+ //读取文件时的缓冲区大小;单位:字节;
20
+ var _CACHE_SIZE = 1024 * 50 ;
21
+
22
+
23
+ /**
24
+ *参数1:时间对象
25
+ *参数2:年月日分隔符,默认是-
26
+ *参数3:时分秒分隔符,默认是:
27
+ */
28
+ var formatDate = function ( d , s1 , s2 ) {
29
+ if ( s1 == null ) {
30
+ var s1 = "-" ;
31
+ }
32
+ if ( s2 == null ) {
33
+ var s2 = ":" ;
34
+ }
35
+ var yyyy = d . getFullYear ( ) ;
36
+ var mo = d . getMonth ( ) < 9 ? ( "0" + ( d . getMonth ( ) + 1 ) ) : d . getMonth ( ) + 1 ;
37
+ var dd = d . getDate ( ) < 10 ? ( "0" + d . getDate ( ) ) : d . getDate ( ) ;
38
+ var hh = d . getHours ( ) < 10 ? ( "0" + d . getHours ( ) ) : d . getHours ( ) ;
39
+ var mi = d . getMinutes ( ) < 10 ? ( "0" + d . getMinutes ( ) ) : d . getMinutes ( ) ;
40
+ var ss = d . getSeconds ( ) < 10 ? ( "0" + d . getSeconds ( ) ) : d . getSeconds ( ) ;
41
+ return yyyy + s1 + mo + s1 + dd + " " + hh + s2 + mi + s2 + ss ;
42
+ }
43
+
44
+ var writeLog = function ( data , ip ) {
45
+ console . log ( data ) ;
46
+ var fs = require ( "fs" ) ;
47
+ var logPath = log_file_path ;
48
+ var options = { encoding :"utf8" , flag :"a" } ;
49
+ if ( data != null || typeof ( data ) == "string" ) {
50
+ var cia = ip == null ?"" :"【" + ip + "】" ;
51
+ fs . writeFile ( logPath , "【" + formatDate ( new Date ( ) ) + "】" + cia + data + "\n" , options , function ( err ) {
52
+ console . log ( err ) ;
53
+ } ) ;
54
+ }
55
+ }
56
+
57
+ var readIndexData = function ( ) {
58
+ //读取文件内容
59
+ var rf = require ( "fs" ) ;
60
+ var filepath = index_file_path ;
61
+ var data = rf . readFileSync ( filepath , 'utf-8' ) ;
62
+ return data ;
63
+ }
64
+
65
+ //打开并读取文件内容
66
+ var openAndGetFileContent = function ( fileName , charset ) {
67
+ var fs = require ( "fs" ) ;
68
+ if ( fileName == null || fileName . length == 0 ) {
69
+ return null ;
70
+ }
71
+ var filepath = basePath + "/" + fileName ;
72
+ var data = null ;
73
+ try {
74
+ var content = fs . readFileSync ( filepath , { encoding :charset } ) ;
75
+ return content ;
76
+ //data = fs.readFileSync(filepath,'binary');
77
+ } catch ( e ) {
78
+ writeLog ( e ) ;
79
+ writeLog ( "读取文件【" + fileName + "】时发生异常" ) ;
80
+ }
81
+ }
82
+
83
+ //获取文件索引页面的html的head标签内容;
84
+ var getIndexHeadHtml = function ( ) {
85
+ var content = openAndGetFileContent ( _INDEX_HEAD_FILE_NAME , "utf8" ) ;
86
+ if ( content != null ) {
87
+ return content ;
88
+ }
89
+ return "" ;
90
+ }
91
+
92
+ //读取文件内容,并用response输出到浏览器终端;
93
+ var openAndReadFileToResponse = function ( fileName , response ) {
94
+ var fs = require ( "fs" ) ;
95
+ if ( fileName == null || fileName . length == 0 ) {
96
+ return null ;
97
+ }
98
+ var filepath = basePath + "/" + fileName ;
99
+ var data = null ;
100
+ try {
101
+ var fd = fs . openSync ( filepath , "r" ) ;
102
+ while ( true ) {
103
+ var buffer = new Buffer ( _CACHE_SIZE , "binary" ) ;
104
+ var len = fs . readSync ( fd , buffer , 0 , buffer . length ) ;
105
+ if ( len > 0 ) {
106
+ response . write ( len == buffer . length ?buffer :buffer . slice ( 0 , len ) , "binary" ) ;
107
+ } else {
108
+ fs . closeSync ( fd ) ;
109
+ break ;
110
+ }
111
+ }
112
+ //data = fs.readFileSync(filepath,'binary');
113
+ return true ;
114
+ } catch ( e ) {
115
+ writeLog ( e ) ;
116
+ writeLog ( "读取文件【" + fileName + "】时发生异常" ) ;
117
+ }
118
+ }
119
+
120
+ var getFileName = function ( path ) {
121
+ if ( path != null && path . length > 0 ) {
122
+ var p = path . indexOf ( "/" ) ;
123
+ var len = path . length ;
124
+ var q = path . indexOf ( "?" ) ;
125
+ if ( p >= 0 && ( p + 1 ) < len ) {
126
+ var end = q > 0 ?q :len ;
127
+ var realName = path . substring ( p + 1 , end ) ;
128
+ //writeLog("解析到文件名:"+realName);
129
+ return realName ;
130
+ }
131
+ }
132
+ return null ;
133
+ }
134
+ //根据文件名获取扩展名
135
+ var getFileExtentision = function ( fileRealName ) {
136
+ if ( fileRealName != null && typeof ( fileRealName ) == "string" && fileRealName . length > 0 ) {
137
+ var i1 = fileRealName . lastIndexOf ( "/" ) ;
138
+ if ( i1 > 0 && ( i1 + 1 ) <= fileRealName . length ) {
139
+ fileRealName = fileRealName . substring ( i1 + 1 , fileRealName . length ) ;
140
+ }
141
+ var p = fileRealName . lastIndexOf ( "." ) ;
142
+ var len = fileRealName . length ;
143
+ if ( p > 0 && ( p + 1 ) < len ) { //有点,非点开头,非点结束;
144
+ var ext = fileRealName . substring ( p + 1 , len ) ;
145
+ return ext ;
146
+ }
147
+ }
148
+ }
149
+
150
+ var extMap = {
151
+ //可扩展的table,键是扩展名,值是Mime类型;
152
+ "323" :"text/h323" , "acx" :"application/internet-property-stream" , "ai" :"application/postscript" , "aif" :"audio/x-aiff" , "aifc" :"audio/x-aiff" , "aiff" :"audio/x-aiff" , "asf" :"video/x-ms-asf" , "asr" :"video/x-ms-asf" , "asx" :"video/x-ms-asf" , "au" :"audio/basic" , "avi" :"video/x-msvideo" , "axs" :"application/olescript" , "bas" :"text/plain" , "bcpio" :"application/x-bcpio" , "bin" :"application/octet-stream" , "bmp" :"image/bmp" , "c" :"text/plain" , "cat" :"application/vnd.ms-pkiseccat" , "cdf" :"application/x-cdf" , "cer" :"application/x-x509-ca-cert" , "class" :"application/octet-stream" , "clp" :"application/x-msclip" , "cmx" :"image/x-cmx" , "cod" :"image/cis-cod" , "cpio" :"application/x-cpio" , "crd" :"application/x-mscardfile" , "crl" :"application/pkix-crl" , "crt" :"application/x-x509-ca-cert" , "csh" :"application/x-csh" , "css" :"text/css" , "dcr" :"application/x-director" , "der" :"application/x-x509-ca-cert" , "dir" :"application/x-director" , "dll" :"application/x-msdownload" , "dms" :"application/octet-stream" , "doc" :"application/msword" , "dot" :"application/msword" , "dvi" :"application/x-dvi" , "dxr" :"application/x-director" , "eps" :"application/postscript" , "etx" :"text/x-setext" , "evy" :"application/envoy" , "exe" :"application/octet-stream" , "fif" :"application/fractals" , "flr" :"x-world/x-vrml" , "gif" :"image/gif" , "gtar" :"application/x-gtar" , "gz" :"application/x-gzip" , "h" :"text/plain" , "hdf" :"application/x-hdf" , "hlp" :"application/winhlp" , "hqx" :"application/mac-binhex40" , "hta" :"application/hta" , "htc" :"text/x-component" , "htm" :"text/html" , "html" :"text/html" , "htt" :"text/webviewhtml" , "ico" :"image/x-icon" , "ief" :"image/ief" , "iii" :"application/x-iphone" , "ins" :"application/x-internet-signup" , "isp" :"application/x-internet-signup" , "jfif" :"image/pipeg" , "jpe" :"image/jpeg" , "jpeg" :"image/jpeg" , "jpg" :"image/jpeg" , "js" :"application/x-javascript" , "latex" :"application/x-latex" , "lha" :"application/octet-stream" , "lsf" :"video/x-la-asf" , "lsx" :"video/x-la-asf" , "lzh" :"application/octet-stream" , "m13" :"application/x-msmediaview" , "m14" :"application/x-msmediaview" , "m3u" :"audio/x-mpegurl" , "man" :"application/x-troff-man" , "mdb" :"application/x-msaccess" , "me" :"application/x-troff-me" , "mht" :"message/rfc822" , "mhtml" :"message/rfc822" , "mid" :"audio/mid" , "mny" :"application/x-msmoney" , "mov" :"video/quicktime" , "movie" :"video/x-sgi-movie" , "mp2" :"video/mpeg" , "mp3" :"audio/mpeg" , "mpa" :"video/mpeg" , "mpe" :"video/mpeg" , "mpeg" :"video/mpeg" , "mpg" :"video/mpeg" , "mpp" :"application/vnd.ms-project" , "mpv2" :"video/mpeg" , "ms" :"application/x-troff-ms" , "mvb" :"application/x-msmediaview" , "nws" :"message/rfc822" , "oda" :"application/oda" , "p10" :"application/pkcs10" , "p12" :"application/x-pkcs12" , "p7b" :"application/x-pkcs7-certificates" , "p7c" :"application/x-pkcs7-mime" , "p7m" :"application/x-pkcs7-mime" , "p7r" :"application/x-pkcs7-certreqresp" , "p7s" :"application/x-pkcs7-signature" , "pbm" :"image/x-portable-bitmap" , "pdf" :"application/pdf" , "pfx" :"application/x-pkcs12" , "pgm" :"image/x-portable-graymap" , "pko" :"application/ynd.ms-pkipko" , "pma" :"application/x-perfmon" , "pmc" :"application/x-perfmon" , "pml" :"application/x-perfmon" , "pmr" :"application/x-perfmon" , "pmw" :"application/x-perfmon" , "pnm" :"image/x-portable-anymap" , "pot" :"application/vnd.ms-powerpoint" , "ppm" :"image/x-portable-pixmap" , "pps" :"application/vnd.ms-powerpoint" , "ppt" :"application/vnd.ms-powerpoint" , "prf" :"application/pics-rules" , "ps" :"application/postscript" , "pub" :"application/x-mspublisher" , "qt" :"video/quicktime" , "ra" :"audio/x-pn-realaudio" , "ram" :"audio/x-pn-realaudio" , "ras" :"image/x-cmu-raster" , "rgb" :"image/x-rgb" , "rmi" :"audio/mid" , "roff" :"application/x-troff" , "rtf" :"application/rtf" , "rtx" :"text/richtext" , "scd" :"application/x-msschedule" , "sct" :"text/scriptlet" , "setpay" :"application/set-payment-initiation" , "setreg" :"application/set-registration-initiation" , "sh" :"application/x-sh" , "shar" :"application/x-shar" , "sit" :"application/x-stuffit" , "snd" :"audio/basic" , "spc" :"application/x-pkcs7-certificates" , "spl" :"application/futuresplash" , "src" :"application/x-wais-source" , "sst" :"application/vnd.ms-pkicertstore" , "stl" :"application/vnd.ms-pkistl" , "stm" :"text/html" , "svg" :"image/svg+xml" , "sv4cpio" :"application/x-sv4cpio" , "sv4crc" :"application/x-sv4crc" , "swf" :"application/x-shockwave-flash" , "t" :"application/x-troff" , "tar" :"application/x-tar" , "tcl" :"application/x-tcl" , "tex" :"application/x-tex" , "texi" :"application/x-texinfo" , "texinfo" :"application/x-texinfo" , "tgz" :"application/x-compressed" , "tif" :"image/tiff" , "tiff" :"image/tiff" , "tr" :"application/x-troff" , "trm" :"application/x-msterminal" , "tsv" :"text/tab-separated-values" , "txt" :"text/plain" , "uls" :"text/iuls" , "ustar" :"application/x-ustar" , "vcf" :"text/x-vcard" , "vrml" :"x-world/x-vrml" , "wav" :"audio/x-wav" , "wcm" :"application/vnd.ms-works" , "wdb" :"application/vnd.ms-works" , "wks" :"application/vnd.ms-works" , "wmf" :"application/x-msmetafile" , "wps" :"application/vnd.ms-works" , "wri" :"application/x-mswrite" , "wrl" :"x-world/x-vrml" , "wrz" :"x-world/x-vrml" , "xaf" :"x-world/x-vrml" , "xbm" :"image/x-xbitmap" , "xla" :"application/vnd.ms-excel" , "xlc" :"application/vnd.ms-excel" , "xlm" :"application/vnd.ms-excel" , "xls" :"application/vnd.ms-excel" , "xlt" :"application/vnd.ms-excel" , "xlw" :"application/vnd.ms-excel" , "xof" :"x-world/x-vrml" , "xpm" :"image/x-xpixmap" , "xwd" :"image/x-xwindowdump" , "z" :"application/x-compress" , "zip" :"application/zip"
153
+ } ;
154
+ //根据扩展名获取Content-Type
155
+ var getContentType = function ( extentision ) {
156
+ if ( extentision != null && typeof ( extentision ) == "string" && extentision . length > 0 ) {
157
+ var ext = extentision ;
158
+ var type = eval ( 'extMap.' + ext ) ;
159
+ return type ;
160
+ }
161
+ }
162
+
163
+ var checkIsFileOrFolder = function ( curName ) {
164
+ if ( curName == "dir" || curName == "ls" ) {
165
+ return "folder" ;
166
+ } else {
167
+ var fs = require ( 'fs' ) ;
168
+ var info = null ;
169
+ try {
170
+ info = fs . statSync ( basePath + "/" + curName ) ;
171
+ } catch ( e ) {
172
+ writeLog ( e ) ;
173
+ }
174
+ if ( info != null ) {
175
+ if ( info . isFile ( ) ) {
176
+ return "file" ;
177
+ } else {
178
+ return "folder" ;
179
+ }
180
+ }
181
+ }
182
+ }
183
+
184
+ //curName可能是:"dir","ls","doc/kms.pdf"
185
+ var getChildFileList = function ( curName ) {
186
+ var fs = require ( "fs" ) ;
187
+ var list = null ;
188
+ try {
189
+ var name = ( curName == null || curName . length == 0 ) ?"" :"/" + curName ;
190
+ list = fs . readdirSync ( basePath + name ) ;
191
+ } catch ( e ) {
192
+ writeLog ( e ) ;
193
+ }
194
+ //console.log(list);
195
+ if ( list != null ) {
196
+ return list ;
197
+ } else {
198
+ return [ ] ;
199
+ }
200
+ }
201
+
202
+ var formatSize = function ( size ) {
203
+ var _1M = 1024 * 1024 ;
204
+ if ( size > _1M ) {
205
+ return ( size / _1M ) . toFixed ( 2 ) + "MB" ;
206
+ } else if ( size > 0 ) {
207
+ return ( size / 1014 ) . toFixed ( 2 ) + "KB" ;
208
+ } else {
209
+ return "" ; //空文件夹
210
+ }
211
+ }
212
+
213
+ var getParentFilePath = function ( fileName ) {
214
+ if ( fileName == "dir" || fileName == "ls" ) {
215
+ return "/" ;
216
+ } else if ( fileName == null || fileName == "" ) {
217
+ return "/" ;
218
+ } else {
219
+ var p = fileName . lastIndexOf ( "/" ) ;
220
+ if ( p > 0 ) {
221
+ return "/" + fileName . substring ( 0 , p ) ;
222
+ } else {
223
+ return "/dir" ;
224
+ }
225
+ }
226
+ }
227
+
228
+ var genFileListHTML = function ( parentPath , list ) {
229
+ //console.log("parentPath=",parentPath,"list=",list);
230
+ var html = "<body onload='onLoad();' >" ;
231
+ html = html + "<table id='id_tb_content_list' class='tb_custom' cellspacing='0px' cellpadding='0px'>\n<tr type='title' ><th align='center' onclick='sortByName();' >名称</th><th align='center' onclick='sortBySize();' >大小</th><th align='center' onclick='sortByDate();' >修改日期</th></tr>\n" ;
232
+ html = html + "<tr type='upper' ><td style='padding-left:10px;padding-right:10px;'><a class=\"css-up icon\" href=\"" + encodeURI ( getParentFilePath ( parentPath ) ) + "\">[上级目录]</a></td><td></td><td></td></tr>" ;
233
+ var fs = require ( "fs" ) ;
234
+ var folderHtmlArr = [ ] ;
235
+ var filesHtmlArr = [ ] ;
236
+ for ( var i = 0 ; i < list . length ; i ++ ) {
237
+ var e = list [ i ] ;
238
+ var name = e ;
239
+ var info = null ;
240
+ try {
241
+ var pp = ( parentPath == null || parentPath . length == 0 ) ?"" :"/" + parentPath ;
242
+ info = fs . statSync ( basePath + pp + "/" + e ) ;
243
+ var size = formatSize ( info . size ) ;
244
+ var dd = formatDate ( info . mtime ) ;
245
+ var isFile = info . isFile ( ) ;
246
+ var css = isFile == true ?"css-file" :"css-folder" ;
247
+ var link = "<a class=\"" + css + " icon\" href=\"" + encodeURI ( pp + "/" + name ) + "\">" + name + "</a>" ;
248
+ var htm = "<tr type='list' onmouseover=\"{style.backgroundColor='#FFFBD1';}\" onmouseout=\"{style.backgroundColor='';}\"><td>" + link + "</td><td size='" + info . size + "' >" + size + "</td><td millions='" + info . mtime . getTime ( ) + "'>" + dd + "</td></tr>" ;
249
+ if ( isFile ) {
250
+ filesHtmlArr . push ( htm ) ;
251
+ } else {
252
+ folderHtmlArr . push ( htm ) ;
253
+ }
254
+ } catch ( e ) {
255
+ writeLog ( e ) ;
256
+ } ;
257
+ }
258
+ html = html + folderHtmlArr . join ( "\n" ) + filesHtmlArr . join ( "\n" ) + "</table></body>" ;
259
+ return html ;
260
+ }
261
+
262
+ //创建服务器
263
+ var createServer = function ( ) {
264
+ var write404HTML = function ( res ) {
265
+ res . writeHead ( 404 , { 'Content-Type' : 'text/html;charset=UTF-8' } ) ;
266
+ res . write ( "<!DOCTYPE html><html><head><meta charset='utf-8'><title>404</title></head><body><h1>404 Not Found</h1></body></html>" ) ;
267
+ }
268
+ var http = require ( 'http' ) ;
269
+ http . createServer ( function ( req , res ) {
270
+ currentIpAddress = getClientIp ( req ) ;
271
+ var u = decodeURI ( req . url ) ;
272
+ writeLog ( "请求地址:" + u , currentIpAddress ) ;
273
+ if ( u == "/" ) {
274
+ //载入主页
275
+ res . writeHead ( 200 , { 'Content-Type' : 'text/html;charset=UTF-8' } ) ;
276
+ var str = "" ;
277
+ try {
278
+ str = readIndexData ( ) ;
279
+ } catch ( e ) {
280
+ writeLog ( e ) ;
281
+ str = "服务器发生异常" ;
282
+ }
283
+ res . end ( str ) ;
284
+ } else if ( u == "/ls" || u == "/dir" ) {
285
+ //输出目录
286
+ var list = getChildFileList ( ) ;
287
+ var html = genFileListHTML ( "" , list ) ;
288
+ res . writeHead ( 200 , { 'Content-Type' : 'text/html;charset=UTF-8' } ) ;
289
+ res . end ( "<!DOCTYPE html><html>" + getIndexHeadHtml ( ) + html + "</html>" ) ;
290
+ } else {
291
+ //var url = require('url');
292
+ //var util = require('util');
293
+ //console.log(util.inspect(url.parse(req.url, true)));
294
+ var fileName = getFileName ( u ) ;
295
+ if ( fileName != null && fileName . length > 0 ) {
296
+ var type = checkIsFileOrFolder ( fileName ) ;
297
+ if ( type == "file" ) {
298
+ var exten = getFileExtentision ( fileName ) ;
299
+ console . log ( "fileName=" + fileName ) ;
300
+ console . log ( "exten=" + exten ) ;
301
+ var contentType = getContentType ( exten ) ;
302
+ if ( contentType != null ) {
303
+ res . writeHead ( 200 , { 'Content-Type' :contentType } ) ;
304
+ }
305
+ //二进制形式读取
306
+ var flag = openAndReadFileToResponse ( fileName , res ) ;
307
+ if ( flag ) {
308
+ res . end ( ) ;
309
+ return ;
310
+ } else {
311
+ write404HTML ( res ) ;
312
+ }
313
+ } else if ( type == "folder" ) {
314
+ var list = getChildFileList ( fileName ) ;
315
+ var html = genFileListHTML ( fileName , list ) ;
316
+ res . writeHead ( 200 , { 'Content-Type' : 'text/html;charset=UTF-8' } ) ;
317
+ res . end ( "<!DOCTYPE html><html>" + getIndexHeadHtml ( ) + html + "</html>" ) ;
318
+ return ;
319
+ } else {
320
+ write404HTML ( res ) ;
321
+ }
322
+ }
323
+ res . end ( ) ;
324
+ }
325
+ } ) . listen ( port ) ;
326
+ writeLog ( "服务器已启动,端口号:" + port ) ;
327
+ }
328
+
329
+ function getClientIp ( req ) {
330
+ var ipAddress ;
331
+ var forwardedIpsStr = req . headers [ 'x-forwarded-for' ] ;
332
+ if ( forwardedIpsStr ) {
333
+ var forwardedIps = forwardedIpsStr . split ( ',' ) ;
334
+ ipAddress = forwardedIps [ 0 ] ;
335
+ }
336
+ if ( ! ipAddress ) {
337
+ ipAddress = req . connection . remoteAddress ;
338
+ }
339
+ return ipAddress ;
340
+ } ;
341
+
342
+ process . on ( 'uncaughtException' , function ( err ) {
343
+ writeLog ( err ) ;
344
+ } ) ;
345
+
346
+ //相当于main方法
347
+ createServer ( ) ;
0 commit comments