NodeJS4-6静态资源服务器实战_range范围请求
range范围请求:向服务器发起请求可以申明我想请求判断内容的范围,从多少个字节到多少个字节,一次要求把所有的内容拿回来,服务器在得到相应的请求之后,从拿到对应的文件,拿到对应的字节返回给客户端.要实现这一功能,请求的时候在RequestHeaders里面放一个range对象和我们定义的范围,都好分割请求多个范围,
- range:bytes = [ start ] - [ end ]
在RequestHeaders里面放一个range对象和我们定义的范围,逗号分割请求多个范围,
- Accept-Ranges:bytes
是在响应中加一个响应头,这里表示服务器可以处理的格式字节
- Content-Range:bytes start-end/total
需要在ResponseHeaders中返回Content-Range表示返回给你的十字街,从哪里开始那里结束
添加一个文件处理range请求,添加range.js
/*参数 totalSize 需要整个的字节数 , req 读到客户端请求range的方位 resp */ module.exports = (totalSize,req,res) =>{ const range = req.headers['range']; //如果拿不到range就返回200,告诉它处理不了 if(!range){ return { code:200 }; } const sizes = range.match(/bytes=(\d*)-(\d*)/) const end = sizes[2] || totalSize - 1; const start = sizes[1] || totalSize - end; //异常情况,返回200 if(start > end || start < 0 || end > totalSize){ return {code:200}; } //设置头部 res.setHeader('Accept-Range','bytes'); res.setHeader('Content-Range',`bytes ${start} - ${end} / ${total} `) res.setHeader('Content-Length',end - start) //可以处理的情况返回以下结果 return { code : 206, start:parseInt(start), end:parseInt(end) } }
在route.js引入range.js
const fs =require('fs')
const path = require('path')
const Handlebars = require('handlebars')
const promisify = require('util').promisify;
const stat = promisify(fs.stat)
const readdir = promisify(fs.readdir);
// //引用range范围
// const range = require('./range')
const config = require('../config/defaultConfig')
const tplPath = path.join(__dirname,'../template/dir.tpl')
const source = fs.readFileSync(tplPath);
const template = Handlebars.compile(source.toString())
//引入新加的mime,对contentType的判断
const mime = require('./mime')
const compress = require('./compress')
//引用range范围
const range = require('./range')
module.exports=async function(req,res,filePath){
try{
const stats =await stat(filePath)
if(stats.isFile()){
const contentType = mime(filePath)
res.statusCode = 200
res.setHeader('content-Type',contentType)
let rs;
const {code,start,end} = range(stats.size, req, res)
if(code === 200){
res.statusCode = 200
rs = fs.createReadStream(filePath)
}else{
res.statusCode = 216 //测试随便定
rs = fs.createReadStream(filePath,{start,end})
}
// let rs = fs.createReadStream(filePath)
if(filePath.match(config.compress)){
rs = compress(rs,req,res)
}
rs.pipe(res);
// fs.readFile(filePath,(err,data)=>{
// res.end(data)
// });
}else if(stats.isDirectory()){
//所有异步调用必须用await
const files =await readdir(filePath);
res.statusCode = 200
res.setHeader('content-Type','text/html')
const dir = path.relative(config.root,filePath)
const data = {
title:path.basename(filePath),
// dir:config.root,
dir:dir?`/${dir}`:'',
files:files.map(file=>{
return {
file,
icon:mime(file)
}
})
}
res.end(template(data));
}
}catch(ex){
console.error(ex);
res.statusCode = 404
res.setHeader('content-Type','text/plain')
res.end(`${filePath} is not a directory or file\n ${ex.error}`)
}
}
主要改变是红框这部分

安装curl来查看,运行
curl -r 0-2 -i http://127.0.0.1:9527/LICENSE
运行结果


浙公网安备 33010602011771号