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中间件。 祝你好运!