断点续传:从文件已经下载的地方开始继续下载。
在以前版本的 HTTP 协议是不支持断点的,HTTP/1.1 开始就支持了。
一般断点下载时才用到 Range 和 Content-Range 实体头
代码示例
http.createServer(function(request, response) {
var pathname = url.parse(request.url).pathname;
var realpath = path.join(__dirname, '..', path.normalize(pathname.replace(/\.\./g, "")));
var ext = path.extname(realpath);
ext = ext ? ext.slice(1) : "unknown";
var contentType = mime[ext].contentType;
fs.exists(realpath, function(exists) {
if (!exists) {
response.writeHead(404, {
'Content-Type': 'text/plain'
});
response.write("This request URL " + pathname + "was not found on this server");
response.end();
} else {
response.setHeader("Content-Type", contentType);
var stats = fs.statSync(realpath);
if (request.headers["range"]) {
var range = parseRange(request.headers["range"], stats.size);
if (range) {
response.setHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + stats.size);
response.setHeader("Content-Length", (range.end - range.start + 1));
var stream = fs.createReadStream(realpath, {
"start": range.start,
"end": range.end
});
response.writeHead('206', "Partial Content");
stream.pipe(response);
} else {
response.removeHeader("Content-Length");
response.writeHead(416, "Request Range Not Satisfiable");
response.end();
}
} else {
var stream = fs.createReadStream(realpath);
response.writeHead('200', "Partial Content");
stream.pipe(response);
}
}
});
}).listen(8080)
parseRange 函数
function parseRange(str, size) {
if (str.indexOf(",") != -1) {
return;
}
if (str.indexOf("=") != -1) {
var pos = str.indexOf("=")
var str = str.substr(6, str.length)
}
var range = str.split("-");
var start = parseInt(range[0], 10)
var end = parseInt(range[1], 10) || size - 1
// Case: -100
if (isNaN(start)) {
start = size - end;
end = size - 1;
// Case: 100-
} else if (isNaN(end)) {
end = size - 1;
}
// Invalid
if (isNaN(start) || isNaN(end) || start > end || end > size) {
return;
}
return {
start: start,
end: end
};
};
mime
{
"css": {
"contentType": "text/css"
},
"gif": {
"contentType": "image/gif",
"mediaType": "image"
},
"html": {
"contentType": "text/html"
},
"ico": {
"contentType": "image/x-icon",
"mediaType": "image"
},
"jpeg": {
"contentType": "image/jpeg",
"mediaType": "image"
},
"jpg": {
"contentType": "image/jpeg",
"mediaType": "image"
},
"js": {
"contentType": "text/javascript"
},
"json": {
"contentType": "application/json"
},
"pdf": {
"contentType": "application/pdf"
},
"png": {
"contentType": "image/png",
"mediaType": "image"
},
"svg": {
"contentType": "image/svg+xml",
"mediaType": "image"
},
"swf": {
"contentType": "application/x-shockwave-flash"
},
"tiff": {
"contentType": "image/tiff"
},
"txt": {
"contentType": "text/plain"
},
"wav": {
"contentType": "audio/x-wav"
},
"wma": {
"contentType": "audio/x-ms-wma"
},
"wmv": {
"contentType": "video/x-ms-wmv"
},
"xml": {
"contentType": "text/xml"
},
"mp4": {
"contentType": "video/mp4",
"mediaType": "video"
},
"m3u8": {
"contentType": "application/x-mpegURL",
"mediaType": "video"
},
"unkown": {
"contentType": "application/octet-stream"
}
}
评论 (0)