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 怎么回事呢?
在使用 Node.js 编写 HTTP 服务器时,处理大文件流式传输时经常需要使用 Transfer-Encoding: chunked
。你遇到的问题是因为在数据被写入响应之前,响应头已经被错误地设置了。这会导致客户端无法正确解析分块编码的数据。
问题分析
在你的代码中,res.write(data)
是在 readable.on("data", ...)
事件中调用的,这意味着数据正在被逐步写入响应体。然而,在 readable.on("end", ...)
事件中,你错误地将 Content-Type
和 Transfer-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
错误。