前言

如何安装node.js,如何搭建一个简易的http服务器我这里就不再赘述了,不懂的同学可以先去学习一下。当然了,我写的也就属于简易版的增强版,大家有什么高见的欢迎提出,然后进入正题。

目录结构

|-server.js
|-router.js
|-test.html
|-css|-test.css
|-js |-test.js

server.js

//原生模块
var http = require('http');
var fs = require('fs');
var url = require('url');
//自定义模块
var router = require('./router.js');
http.createServer(function(request,response){
//获取客户端访问的路径
var pathname = url.parse(request.url).pathname;
//如果用户只输入域名就改变访问路径,并发送主页的内容给客户端
if(pathname == "/"){
pathname = "/index.html";
}
  //获取当前请求客户端的IP地址
var ipv4 = get_client_ipv4(request);
//输出日志到控制台
showLog(ipv4,("请求"+decodeURI(pathname)));
//判断文件是否存在
fs.exists(__dirname + decodeURI(pathname),function(exists){
if(exists){
//使用router模块的函数
router.readFileBySuffixName(pathname,fs,request,response);
}else{
console.log(decodeURI(pathname)+"文件不存在!");
//文件不存在,向客户端发送404状态码,并发送该文件不存在的字符串
response.writeHead(404,{"Content-Type":"text/plain"});
response.end(pathname+"文件不存在!");
}
});
}).listen(80); //监听80端口 console.log('web服务已运行!'); /**
* @desc 获取IPV4地址
* @param req htttp.request
* @return string 32位IP地址
*/
function get_client_ipv4(req) {
//获取任意浏览器的IP地址,
var ip = req.headers['x-forwarded-for'] ||
req.ip ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress || '';
//获取到的IP地址中存在IPV4和IPV6的地址,我们只需要IPV4的地址
if(ip.split(',').length>0){
ip = (ip.split(',')[0]).match(/(\d+\.\d+\.\d+\.\d+)/)[0];
}
return ip;
}; /**
* @desc 向控制台输出日志,自动在头部添加时间、地址
* @param ipv4 string
* @param message string
*/
function showLog(ipv4,message){
//获取当前时间
var date = new Date();
//转换为本地时间的字符串形式并输入到控制台
console.log(date.toLocaleDateString() + " " + date.toLocaleTimeString() +
" " + ipv4 + " " + message);
}

首先引入模块,使用http.createServer创建http服务器,并监听80端口;http.createServer的回调函数接收两个值,一个request请求对象,一个response响应对象,request对象可以获取到客户端请求的信息,response对象用来返回数据到客户端;上面创建了两个简单的工具函数,分别用来获取客户端的IPV4地址、向控制台输出日志;使用fs.exists函数判断客户端请求的文件是否存在,如果不存在则返回404状态码,如果存在,则使用下面router.js中创建的readFileBySuffixName函数,读取相应的文件并根据后缀名设置响应头,然后发送数据到客户端。

router.js

/**
* @desc 根据后缀名读取文件
* @param pathname string 文件路径 url.parse(request.url).pathname
* @param fs fs
* @param request htttp.request
* @param response https.response
*/
exports.readFileBySuffixName = function(pathname,fs,request,response){
var ext = pathname.match(/(\.[^.]+|)$/)[0];//取得后缀名
switch(ext){ //根据后缀名读取相应的文件,设置响应头,并发送到客户端
case ".css":
case ".js":
//读取文件
fs.readFile("."+request.url,'utf-8',function(err,data){
if(err) throw err;
response.writeHead(200,{ //根据不同的后缀设置不同的响应头
"Content-Type":{
".css":"text/css",
".js":"application/javascript",
}[ext]
});
response.write(data); //发送文件数据到客户端
response.end(); //发送完成
});
break;
//jpg、gif、png后缀的图片
case ".jpg":
case ".gif":
case ".png":
//二进制读取文件
fs.readFile("."+decodeURI(request.url),'binary',function(err,data){
if(err)throw err;
response.writeHead(200,{
"Content-Type":{
".jpg":"image/jpeg",
".gif":"image/gif",
".png":"image/png",
}[ext]
});
response.write(data,'binary'); //发送二进制数据
response.end();
});
break;
case ".mp4":
//读取文件的状态
fs.stat('.'+decodeURI(request.url),function(err,stats){
if(err){
if(err.code === 'ENOENT'){
return response.sendStatus(404);
}
response.end(err);
}
//断点续传,获取分段的位置
var range = request.headers.range;
if(!range){
//206状态码表示客户端通过发送范围请求头Range抓取到了资源的部分数据
//416状态码表示所请求的范围无法满足
return response.sendStatus(416);
}
//替换、切分,请求范围格式为:Content-Range: bytes 0-2000/4932
var positions = range.replace(/bytes=/,"").split("-");
//获取客户端请求文件的开始位置
var start = parseInt(positions[0]);
//获得文件大小
var total = stats.size;
//获取客户端请求文件的结束位置
var end = positions[1] ? parseInt(positions[1],10):total -1;
//获取需要读取的文件大小
var chunksize = (end-start) + 1; response.writeHead(206,{
"Content-Range":"bytes "+ start+"-"+end+"/"+total,
"Accept-Ranges":"bytes",
"Content-Length":chunksize,
"Content-Type":"video/mp4"
});
//创建读取流
var stream = fs.createReadStream('.'+decodeURI(request.url),{start:start,end:end})
  .on("open",function(){
stream.pipe(response); //读取流向写入流传递数据
}).on("error",function(err){
response.end(err);
});
});
break;
      case ".rar":
//同步读取文件状态
  var stats = fs.statSync("." + decodeURI(request.url));
response.writeHead(200,{
"Content-Type": "application/octet-stream", //相应该文件应该下载
//模板字符串
"Content-Disposition": `attachment; filename = ${pathname.replace("/","")}`,
"Content-Length":stats.size
});
//管道流
fs.createReadStream("." + decodeURI(request.url)).pipe(response);
break;
        //以上都不匹配则使用默认的方法
      default:
       fs.readFile('.'+pathname,'utf-8',function(err,data){
response.writeHead(200,{
"Content-Type":"text/html"
});
response.write(data);
response.end();
});
}
}

router.js文件中只有一个readFileBySuffixName函数,该函数的作用是判断客户端访问文件的后缀名,css、js、图片、mp4视频、rar文件等都能成功返回到客户端;其中视频和下载文件使用流传输;因为如果不使用流的话,服务器要先缓存文件,然后再发送文件到客户端;使用HTML5视频的客户端会发送一个Content-Range的值到服务器,服务器根据这个range值读取一个文件指定的部分,并返回这个特定的部分数据到客户端,就实现了视频的断点续传,你可以随意的跳转到视频的任意一部分了!

进入项目文件夹,输入

node ./server.js

服务器端输出日志和测试页面

favicon.ico文件是该页面的图标文件,第一次进入页面浏览器会自动请求。

使用原生node.js搭建HTTP服务器,支持MP4视频、图片传输,支持下载rar文件的更多相关文章

  1. 使用 Node.js 搭建 Web 服务器

    使用Node.js搭建Web服务器是学习Node.js比较全面的入门教程,因为实现Web服务器需要用到几个比较重要的模块:http模块.文件系统.url解析模块.路径解析模块.以及301重定向技术等, ...

  2. 学习 node.js 搭建web服务器

    开始 学习使用 node.js 首先完成搭建一个 web服务器.myweb.js var http = require('http'); var url = require('url'); var h ...

  3. 用node.js搭建本地服务器

    我的第一篇笔记来写写node.js,我对node.js的并不是很了解,基本的项目路径变换还是会的.原先我下载node.js就是我想学vue.js,后来因为工作的繁忙搁浅了我的计划.最近在学习phase ...

  4. node.js搭建Web服务器

    Node.js 博客搭建 一. 学习需求 Node 的安装运行 会安装node,搭建node环境 会运行node. 基础模块的使用 Buffer:二进制数据处理模块 Event:事件模块 fs:文件系 ...

  5. node.js搭建https服务器

    HTTPS简介 HTTPS:(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版. ...

  6. Node.js学习笔记(五) --- 使用Node.js搭建Web服务器

    1. Node.js 创建的第一个应用 1.引入http模块 var http = require("http"); 2. 创建服务器接下来我们使用 http.createServ ...

  7. express+node.js搭建的服务器和在sublimeServer下的页面请求报跨域错误

    1.前端页面使用vue中的axios请求nodejs响应.报以下错误: Failed to load http://localhost:3000/users/validate: Response to ...

  8. 使用node.js搭建本地服务器

    第一步安装node:https://nodejs.org/zh-cn/download/ 接下来就需要安装http的镜像文件 打开cmd:输入以下命令 npm install http-server ...

  9. 如何使用Node.js搭建一个服务器

    在node环境中运行下面的代码 "use strict"; const http = require("http"), path = require(" ...

随机推荐

  1. LNMP分离

    1.Nginx 找php 在nginx 配置文件的server里 添加 location ~.*\.(php|php5)?$ { root    /var/www/html/wwwcom; fastc ...

  2. android Api操作SQLite数据库的示例代码

    import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.databa ...

  3. 用Python解方程

    一元一次方程 例题1: 这是北师大版小学六年级上册课本95页的一道解方程练习题: 大家可以先口算一下,这道题里面的x的值为200 接下来我们用python来实现,代码如下,每一句代码后面都写有解释语: ...

  4. 导入现有java工程

    1)错误:点击File-->open File 这样只能导入单个文件: 2)正确:File-->Import--> 然后下一步下一步即可.

  5. appium+python+Windows自动化测试文档

    appium+python自动化测试文档 一.认识appium 1.    什么是appium appium是开源的移动端自动化测试框架: appium可以测试原生的.混合的.以及移动端的web项目: ...

  6. 【图像处理与医学图像处理】YUV与RGB格式转换速度几种方法对比

    [视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...

  7. NProgress颜色的修改以及在Vue中的使用

    一.NProgress的作用是在站内进行页面之间的跳转的时候,在浏览器的顶部显示一个进度,使用非常简单,可以在百度一下. 二.如何修改NProgress默认的进度条颜色?如下图,修改为自己想要的颜色即 ...

  8. ES6中Set和Map

    1.Set 实例的创建 Set实例它类似于数组,但是成员的值都是唯一的,没有重复的值. Set本身是一个构造函数用来生成Set数据结构. Set 函数可以接受一个数组(或者具有 iterable 接口 ...

  9. MQTT 简介及协议原理

    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种构建于TCP/IP协议上基于发布/订阅(publish/subscribe)模式的“轻量 ...

  10. navicat建立本地连接出错解决

    使用navicat建立本地连接时报错: 2.设置用户配置项 (1) 查看用户信息 select host,user,plugin,authentication_string from mysql.us ...