Nodejs http server response 客户端报出ERR_INVALID_CHUNKED_ENCODING

Nodejs http server response 客户端报出ERR_INVALID_CHUNKED_ENCODING

我先这样写

	fs.createReadStream(p).pipe(res);

没有问题,但是

  var readable = fs.createReadStream(p);
	readable.on("data", function(data){
		res.write(data);
	});
	readable.on("end", function(){
		// write response head
		res.writeHead(200, {
			"Content-Type": "text/html",
			"Transfer-Encoding": "chunked"
		});
		res.end();
	});
	readable.on("error", function(){
		res.statusCode = 500;
		res.end("500 Internal Error");
	});

这样的话客户端就报出ERR_INVALID _CHUNKED_ENCODING 怎么回事呢?


6 回复

在使用 Node.js 编写 HTTP 服务器时,处理大文件流式传输时经常需要使用 Transfer-Encoding: chunked。你遇到的问题是因为在数据被写入响应之前,响应头已经被错误地设置了。这会导致客户端无法正确解析分块编码的数据。

问题分析

在你的代码中,res.write(data) 是在 readable.on("data", ...) 事件中调用的,这意味着数据正在被逐步写入响应体。然而,在 readable.on("end", ...) 事件中,你错误地将 Content-TypeTransfer-Encoding 设置到了响应头中,并且立即调用了 res.end(),这会导致客户端接收到一个空的响应体(因为所有数据已经在 data 事件中被写入),并且由于错误的分块编码设置导致了 ERR_INVALID_CHUNKED_ENCODING 错误。

解决方案

正确的做法是在发送数据之前先设置响应头。以下是修正后的代码示例:

const http = require('http');
const fs = require('fs');

const server = http.createServer((req, res) => {
	const p = 'path/to/your/file'; // 替换为你的文件路径
	const readable = fs.createReadStream(p);

	// 在开始读取文件之前设置响应头
	res.writeHead(200, {
		"Content-Type": "text/html",
		"Transfer-Encoding": "chunked"
	});

	readable.pipe(res); // 使用管道直接传输数据,避免手动管理分块编码
});

server.listen(3000, () => {
	console.log('Server running at http://localhost:3000/');
});

在这个例子中,我们使用了 readable.pipe(res) 方法来自动处理分块编码。Node.js 的 pipe 方法会自动处理分块编码并确保响应头在数据被写入之前正确设置。这种方法不仅简化了代码,还减少了错误的可能性。

总结

当处理大文件或需要流式传输数据时,使用 pipe 方法是一个更安全、更简单的方法。它能自动处理分块编码和其他细节,使你的代码更加健壮。


加了个buffer 问题没有了 谁能解释下是为什么吗 谢啦

  var readable = fs.createReadStream(p);
	var buffer = new Buffer("");
readable.on("data", function(data){
  // res.write(data);
	buffer = Buffer.concat([buffer, data]);
});

readable.on("end", function(){
	// write response head
	res.writeHead(200, {
		"Content-Type": "text/html",
		"Transfer-Encoding": "chunked"
	});
	res.end(buffer);
});

readable.on("error", function(){
	res.statusCode = 500;
	res.end("500 Internal Error");
});</code></pre></blockquote>

var readstream = fs.createReadStream(filepath,{encoding:‘binary’}); res.write(data,‘binary’); res.end()

ON(data)会被多次触发。这么写

  var datax='';
  var readable = fs.createReadStream(p,'binary');
  readable.on("data", function(data){
      datax +=data;
  });

readable.on(“end”, function(){ // write response head res.writeHead(200, {“Content-Type”: “text/html” }); res.write(datax,‘binary’); res.end(); });

readable.on(“error”, function(){ res.statusCode = 500; res.end(“500 Internal Error”); });

因为那个不能执行的代码是先发送响应的主体再发送的响应头,这个是不正确的,应该要先发送响应头再发送响应主体。

客户端报出 ERR_INVALID_CHUNKED_ENCODING 错误通常是因为 HTTP 响应头中的 Transfer-Encoding: chunked 与响应体的格式不匹配。在你的代码中,问题在于你在数据传输完成后才设置了 Transfer-Encoding: chunked 响应头,这会导致客户端无法正确解析分块编码的数据。

正确的做法是在开始写入数据之前设置好响应头。以下是修改后的代码示例:

var http = require('http');
var fs = require('fs');

http.createServer(function (req, res) {
    var p = 'path/to/your/file'; // 文件路径

    var readable = fs.createReadStream(p);
    
    // 设置响应头
    res.writeHead(200, {
        "Content-Type": "text/html",
        "Transfer-Encoding": "chunked"
    });

    // 将可读流直接管道到响应对象
    readable.pipe(res);

    readable.on("error", function(err) {
        res.statusCode = 500;
        res.end("500 Internal Error");
    });
}).listen(3000);

在这个例子中,我们首先设置了响应头,然后使用 .pipe() 方法将文件可读流直接连接到响应对象。这种方式不仅简洁,而且避免了手动处理数据事件和结束事件,减少了错误发生的可能性。

通过这样的方式,你可以确保数据以分块编码的方式正确发送给客户端,从而避免 ERR_INVALID_CHUNKED_ENCODING 错误。

回到顶部