前言

如何安装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. JAVA 基础编程练习题5 【程序 5 判断分数等级】

    5 [程序 5 判断分数等级] 题目:利用条件运算符的嵌套来完成此题:学习成绩>=90 分的同学用 A 表示,60-89 分之间的用 B 表示, 60 分以下的用 C 表示. 程序分析:(a&g ...

  2. TextInput组件的常用属性

    1.TextInput组件基本介绍: TextInput是一个允许用户在应用中通过键盘输入文本的基本组件.本组件的属性提供了多种特性的配置,譬如自动完成.自动大小写.占位文字,以及多种不同的键盘类型( ...

  3. BN和L2 NORM的区别

    bn是拉平各个feature的差异,而l2 norm是拉平各个样本的差异,本来各个样本的模长千变万化,按照距离的概念,差别是很大的,但是l2 norm后,距离就变得有一个上界了,显然样本间差异变小了. ...

  4. Spring Boot开发Web应用之JSP篇

    前言 上一篇介绍了Spring Boot中使用Thymeleaf模板引擎,今天来介绍一下如何使用SpringBoot官方不推荐的jsp,虽然难度有点大,但是玩起来还是蛮有意思的. 正文 先来看看整体的 ...

  5. 0-linux简介

    linux是什么? linux有什么用? linux学了能做什么? 潜台词:linux能找什么工作?有没有钱和前途? linux要学什么? 服务的安装,配置,维护 保障服务/系统/业务的稳定,能长期不 ...

  6. python-Web-django-路由保护

    from django.shortcuts import redirect,HttpResponse from app01.models import * import re def ddff(mod ...

  7. ASP.NET Core 入门笔记8,ASP.NET Core MVC 分部视图入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)分部视图简介 ASP.NET Core MVC (Razor)分部视图基础教程 ASP.NET Core MVC (Raz ...

  8. SpringCloud学习(SPRINGCLOUD微服务实战)一

    SpringCloud学习(SPRINGCLOUD微服务实战) springboot入门 1.配置文件 1.1可以自定义参数并在程序中使用 注解@component @value 例如 若配置文件为a ...

  9. centos超详细搭建jumpserver跳板机

    一.官网 https://docs.jumpserver.org/zh/master/  二.一站式.分布式安装文档  三.选择最新版 四.在线安装文档 五.按文档部署(4G.二核.50G硬盘)  六 ...

  10. 安装glance

    在控制节点上执行 controllerHost='controller' MYSQL_PASSWD='m4r!adbOP' GLANCE_PASSWD='glance1234!' 1.创建数据库 my ...