Node.js:分块传输编码
该代码是否有效的HTTP / 1.1?
var fs = require('fs') var http = require('http') var buf=function(res,fd,i,s,buffer){ if(i+buffer.length<s){ fs.read(fd,buffer,0,buffer.length,i,function(e,l,b){ res.write(b.slice(0,l)) //console.log(b.toString('utf8',0,l)) i=i+buffer.length buf(res,fd,i,s,buffer) }) } else{ fs.read(fd,buffer,0,buffer.length,i,function(e,l,b){ res.end(b.slice(0,l)) fs.close(fd) }) } } var app = function(req,res){ var head={'Content-Type':'text/html; charset=UTF-8'} switch(req.url.slice(-3)){ case '.js':head={'Content-Type':'text/javascript'};break; case 'css':head={'Content-Type':'text/css'};break; case 'png':head={'Content-Type':'image/png'};break; case 'ico':head={'Content-Type':'image/x-icon'};break; case 'ogg':head={'Content-Type':'audio/ogg'};break; case 'ebm':head={'Content-Type':'video/webm'};break; } head['Transfer-Encoding']='chunked' res.writeHead(200,head) fs.open('.'+req.url,'r',function(err,fd){ fs.fstat(fd,function(err, stats){ console.log('.'+req.url+' '+stats.size+' '+head['Content-Type']+' '+head['Transfer-Encoding']) var buffer = new Buffer(100) buf(res,fd,0,stats.size,buffer) }) }) } http.createServer(app).listen(8000,"127.0.0.1") console.log('GET http://127.0.0.1:8000/appwsgi/www/index.htm')
我认为我在这里违反HTTP / 1.1? 文本文件似乎工作正常,但这可能是巧合。 我的头是“200 OK”还是需要它是“100”? 一个头是否足够?
如果你正在做分块传输编码,你实际上需要设置这个头:
Transfer-Encoding: chunked
你可以从谷歌返回的头文件中看到,它为主页和最有可能的其他页面分块传输:
HTTP/1.1 200 OK Date: Sat, 04 Jun 2011 00:04:08 GMT Expires: -1 Cache-Control: private, max-age=0 Content-Type: text/html; charset=ISO-8859-1 Set-Cookie: PREF=ID=f9c65f4927515ce7:FF=0:TM=1307145848:LM=1307145848:S=fB58RFtpI5YeXdU9; expires=Mon, 03-Jun-2013 00:04:08 GMT; path=/; domain=.google.com Set-Cookie: NID=47=UiPfl5ew2vCEte9JyBRkrFk4EhRQqy4dRuzG5Y-xeE---Q8AVvPDQq46GYbCy9VnOA8n7vxR8ETEAxKCh-b58r7elfURfiskmrOCgU706msiUx8L9qBpw-3OTPsY-6tl; expires=Sun, 04-Dec-2011 00:04:08 GMT; path=/; domain=.google.com; HttpOnly Server: gws X-XSS-Protection: 1; mode=block Transfer-Encoding: chunked
编辑哎呀,那读太复杂了:
var app = function(req,res){ var head={'Content-Type':'text/html'} switch(req.url.slice(-3)){ case '.js':head={'Content-Type':'text/javascript'};break; case 'css':head={'Content-Type':'text/css'};break; case 'png':head={'Content-Type':'image/png'};break; case 'ico':head={'Content-Type':'image/x-icon'};break; case 'ogg':head={'Content-Type':'audio/ogg'};break; case 'ebm':head={'Content-Type':'video/webm'};break; } res.writeHead(200,head) var file_stream = fs.createReadStream('.'+req.url); file_stream.on("error", function(exception) { console.error("Error reading file: ", exception); }); file_stream.on("data", function(data) { res.write(data); }); file_stream.on("close", function() { res.end(); }); }
你去,一个很好的stream缓冲区,你写。 这是一篇博客文章,我用不同的方式来阅读文件。 我build议您仔细查看,以便在节点的asynchronous环境中查看如何更好地使用文件。
由于Node.js隐式设置了“ Transfer-Encoding:chunked ”,所有我需要发送头文件的内容types是charset,如下所示:
'Content-Type': 'text/html; charset=UTF-8'
最初是这样的:
'Content-Type': 'text/html'
…没有工作。 指定“ charset = UTF-8 ”立即强制Chrome呈现分块响应。
你为什么手动做所有的fs
操作? 你可能会更好使用fs.createReadStream()
函数。
最重要的是,我的猜测是Chrome期待您返回206
响应代码。 检查req.headers.range
,看看Chrome是否在req.headers.range
媒体文件的“范围”被返回。 如果是,那么你将只需要发回networking浏览器所请求的那部分文件。
为什么要重新发明轮子? 有大量的节点模块为你做这种事情。 尝试Connect / Express' static
中间件。 祝你好运!