前几天,一个同事说他写的web静态服务器不支持音视频的播放,现简单实现一下。

原理:实现http1.1协议的range部分。

其实这一点都不神秘,我们常用的下载工具,如迅雷,下载很快,还支持断点续传,就是利用http协议的range和多线程实现的。假如下载一个1MB的文件,如果开一个线程下载,那么只能从头到尾依次下载这个文件,这样不可能提升速度。通常,下载工具会开很多个线程,这里暂且假设是4个,然后这4个线程同时分别下载这1MB的0~255KB、256-511KB、512~767KB和768~1024KB,很显然,理论上速度提升了4倍。

那么怎么将服务器上的1MB文件分成4份呢?这就是range的强大功能了!

当请求下载文件时,带有

  Range: bytes=0-255[,256-511]  //这里表示0~255个字节,如果请求多个分段,用逗号隔开

服务器响应请求时发现头部带有Range,那么做出响应:

  Content-Range: bytes 0-255/789  //789就是整个文件的大小了

  Content-Length: 256

同时status变为,而不是200,并发送这一段数据给客户端,这样客户端接收到的数据就是整个文件的一部分了!

range的请求头还可以是:

  • Range: bytes=0-  //整个文件
  • Range: bytes=-200  //最后200个字节
  • Range: bytes=200-  //200字节后的所有字节
  • Range: bytes=0-0,-1  //第一、最后一个字节

看代码如何实现

//判断是请求头中是否有range部分
if(request.headers.range){
var size = stat.size;//获取文件大小
//暂且写在这里
function getRange(){
var range = request.headers.range; if(range.indexOf(",") != -1){//这里只处理了一个分段的情况
return false;
}
//range大约长这样子:bytes=0-255[,256-511]
var parts = range.replace(/bytes=/, '').split("-");
var partiaStart = parts[0];
var partialEnd = parts[1]; var start = parseInt(partiaStart);//起始位置
//如果是bytes=0-,就是整个文件大小了
var end = partialEnd ? parseInt(partialEnd) : size - 1; if(isNaN(start) || isNaN(end)) return false;
//分段的大小
var chunkSize = end - start + 1; return {'start': start, 'end': end, 'chunkSize': chunkSize};
} var rangeData = getRange();
if(rangeData){
//createReadStream这东西原生支持range,是不是很爽?
var raw = fs.createReadStream(realPath, {'start': rangeData.start, 'end': rangeData.end});
//状态码当然是206了
response.writeHead(206, 'Partial Content', {
'Content-Type' : contentType,
'Content-Range' : 'bytes ' + rangeData.start + '-' + rangeData.end + '/' + size,
'Content-Length' : rangeData.chunkSize
});
raw.pipe(response);
}else{
response.writeHead(416, "not ok!");
response.end();
}
}else{
//状态码200
}

大概就是这样子,其他部分略去。

用html5的audio标签试验下mp3的播放:

<audio src="audio/test.mp3" controls="controls" preload="auto" autoplay="autoplay"></audio>

得到的请求和响应头如下:

下图是MP3文件加载到6MB时的截图,这时音乐已经播放超过一半了,所以可不是加载完成才播放的。

这样web服务器就实现range功能,可以处理多媒体文件了,当然只是非常简单的实现,想了解更多可以查阅W3的网站(前面说的下载、断点续传什么的就不验证了,客户端也搞不明白)

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

Nodejs实现web静态服务器对多媒体文件的支持的更多相关文章

  1. Web静态服务器

    Web静态服务器 编程微刊 Web静态服务器-1-显示固定的页面 #coding=utf-8 import socket def handle_client(client_socket): " ...

  2. Python建立web静态服务器

    原文地址:http://www.bugingcode.com/blog/python_html_web_server.html python作为工具,提供了很多好用的命令,比如有时候突然需要建立一个解 ...

  3. 08.Web服务器-3.Web静态服务器

    1.显示固定的页面 from socket import * from multiprocessing import * import os def handleClient(clientSocket ...

  4. nodejs 搭建本地静态服务器

    1. http-server 参看 https://www.npmjs.com/package/http-server 使用http-server搭建本地静态服务器 全局安装http-server n ...

  5. python高级编程之 web静态服务器

    返回固定数据 import socket def request_handler(new_client_socket): """ 响应客户端请求的核心函数 "& ...

  6. [置顶] java web 动态服务器

    写了一个java web 动态服务器,主要通过内部类来实现,动态类使用了外部类,采用了 classforname 实例化,动态类的构造方法不能带参数, 效果都出来了,分享给有需要的 朋友.判断做的不够 ...

  7. nodejs http静态服务器

    使用nodejs写的很简单的静态服务器,没有做cluster处理,没有做缓存处理,不支持访问文件夹,功能只有一个,就是获取到文件后再返回文件内容. var fs = require('fs'); va ...

  8. 安装nodeJs静态服务器(NodeJs Express MVC 框架)

    安装 NodeJs Express MVC 框架   新建项目文件夹   打开cmd 执行以下操作:   一.使用Express框架 1)安装express3 $: npm install -g ex ...

  9. Web前端页面的浏览器兼容性测试心得(一)搭建测试用本地静态服务器

    自从实习以来,我体验了由一个人编程再到多人协作编程的转换.同时也接触了很多新鲜事物,学到了很多东西.工作时,常常需要多个人协同测试一张H5页面(PC.手机.平板等跨设备测试),也会经常把页面给PM或老 ...

随机推荐

  1. [转] shell字符串操作方法,以及实例

    每一种语言都有他独自的字符串操作方法,shell也一样,下面以以例子的方式,简单介绍常用方法. 1,取得字符串长度 string=abc12342341 //等号二边不要有空格 echo ${#str ...

  2. WPF-数据绑定:日期时间格式

    WPF-数据绑定:日期时间格式绑定后自定义格式的例子. 我刚才遇到的问题是绑定完之后,星期始终显示为英文.需要一个属性ConverterCulture制定区域. 如下: {Binding dateti ...

  3. myeclipse配置下tomcat debug启动很无比慢

    myeclipse配置下tomcat debug启动很无比慢,而run启动很快今天照常使用MyEclipse 6.5 Blue Edition进行开发,但是却遇到一个怪问题.在MyEclipse环境下 ...

  4. class_create(),device_create()使用

    开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点(包括ldd3中不少例子也是这样),实际上现在Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/de ...

  5. int main(int argc,char* argv[]) 简单理解

    (1)第一个int代表整个main函数的返回值,若函数正常执行完毕,返回0,异常返回则是-1 (2)int argc代表命令行参数的总个数,既然是个数,那就是整型的,即:int; (3)char* a ...

  6. NOIP2015-stone(二分答案)

    这道题在考试时二分答案写炸了,结果得了20分.....同学有用贪心写的(对,贪心!!)都得了30,我感到了深深的恶意.这段时间在忙转语言,现在重新整理一下NOIP的题. 题目来源:vijos 题目如下 ...

  7. mysql federated engine

    mysql)) -> engine=federated -> connection='mysql://root@localhost:3306/t1/t';

  8. 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

    // test20.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...

  9. win8双屏敲代码

    23寸,AOC冠杰("AOC I2369V 23英寸LED背光超窄边框IPS广视角液晶显示器(银色)") 某东,920买入.

  10. android 解析XML方式(三)

    上一节中,我们使用SAX方式解析xml文档, SAX方式是基于事件驱动的.当然android的事件机制是基于回调函数的.在这一节中,我们用另外一种方式解析xml文档,这种方式也是基于事件驱动的,与SA ...