【问题标题】:Node.js: write after end error while writing on file decompressed gzip post dataNode.js:写入文件解压缩后的 gzip 发布数据时写入结束错误
【发布时间】:2017-03-27 19:04:59
【问题描述】:

我写在这里是因为我遇到了一个我自己无法解决的 Node.js 问题。让我们只关注我编写的简单服务器的 POST 请求。 我的服务器必须只接受包含 gzip 压缩数据的 POST 请求,然后解压缩它们并将提取的内容写入一个本地文件,该文件的名称位于变量“path”内。 我几乎完成了刚才解释的所有内容,我还想出了如何解压缩 gzip 数据,但我不明白如何将内容写入文件。

POST 请求(在 Debian 上执行)总是如下:

curl -sS -X POST -H "Content-Type: application/gzip" --data-binary @<(echo "Uncompressed data" | gzip) http://192.168.1.66:8080/?path=test.txt

我以许多不同的方式尝试了很多次,但尽管在我看来是正确的,但执行总是给我这个输出:

Adding Uncompressed data
 to buffer..
Entering ws on finish...
buffer: 'Uncompressed data
'
events.js:163
      throw er; // Unhandled 'error' event
      ^

Error: write after end
    at writeAfterEnd (_stream_writable.js:191:12)
    at WriteStream.Writable.write (_stream_writable.js:238:5)
    at Gunzip.<anonymous> (C:\Users\Public\exercise2.js:54:14)
    at emitNone (events.js:91:20)
    at Gunzip.emit (events.js:188:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:80:11)
    at process._tickCallback (internal/process/next_tick.js:104:9)

我的代码是这个:

const fs   = require('fs');
const http = require('http');
const url  = require('url');
const zlib = require('zlib');
const home = 'C:\\Users\\Public\\server_dir'

function handle_get(path,cb){
    fs.readdir(path,
           (err,files) => {
               if(err) cb(500,JSON.stringify({error : err.message, files: files||null})+'\n')
               else cb(200,JSON.stringify({error : null, files : files})+'\n')
           })
}

function handle_post(req,path,cb){
    function warn(err,event){
        if(err) console.warn(`Request ${event}, could not close ${path}`)
        else console.warn(`Request ${event}, ${path} closed succesfully`)
    }

    console.log("\n\nHeaders="+req.headers+"\n\n")
    var encoding  = req.headers['content-encoding']
    var cont_type = req.headers['content-type']

    if ((encoding == undefined || encoding.indexOf("gzip") <= 0) && cont_type.indexOf("gzip") <= 0)
      return cb(400, JSON.stringify({error : "Bad request: gzip encoding requested"})+'\n')

    fs.open(path,'w',0o644,
        (err,fd)=>
        {
            if(err) return cb(500,JSON.stringify({error : err.message})+'\n')
            const ws=fs.createWriteStream(null,{fd:fd})

            ws.on('finish',() => {
            console.log("Entering ws on finish...");
            cb(200, JSON.stringify({error : null, "written bytes":ws.bytesWritten})+'\n')
            })
            req.on('aborted',()=>fs.close(fd,err=>warn(err,'aborted')))
            req.on('error',(err)=>{
                fs.close(fd,err=>warn(err,'error'))
                cb(500,JSON.stringify({error : err.message, "written bytes":ws.bytesWritten})+'\n')
            })

            var buffer = [];
            var gunzip = zlib.createGunzip();
            gunzip.on('data',function(data) {
            var uncompressed = data.toString();
            console.log("Adding '"+uncompressed+"' to buffer..")
            buffer.push(uncompressed);
            //ws.write(uncompressed); // I've also tried this but it does not work
            }).on('end', function() {
                console.log("buffer: '"+buffer+"'");
                ws.write(buffer.join(""));
                ws.end();
            }).on('error',function(e) {
                console.log("error: "+e);
            })

            req.pipe(gunzip);
            req.pipe(ws);
        })
}

var s=http.createServer(
    (req,res) => {
        console.log("Request: "+req.method+" URL: "+req.url)

        function send(code,json_string){
            res.writeHead(code,{"Content-Type" : "application/json"})
            res.end(json_string)
        }

        if(req.method=='GET') handle_get(home+req.url,send)
        if(req.method=='POST') {
            var parsed_url=url.parse(req.url,true)
            var path=parsed_url.query.path
            console.log(parsed_url);
            if(!path)
                return send(400, JSON.stringify({error : 'Missing path'})+'\n')
            handle_post(req,home+path,send)
        }
  })

s.listen(8080);

提前谢谢你。

【问题讨论】:

  • 我注意到的一件事是,您正在同时从req 传输到 2 个单独的写入流。这也应该导致另一个问题,因为它们都在同时刷新流。这意味着两个目标都将具有不完整的请求数据版本。此外,当您使用fs.createWriteStream() 时,应该监听'close' 事件而不是'finish' 事件。

标签: javascript node.js http gzip zlib


【解决方案1】:

我解决了它,在与 Gunzip 相关的“结束”事件中找到与 ws 相关的代码。 编辑代码:

var buffer = [];
var gunzip = zlib.createGunzip();
gunzip.on('data',function(data) {
  var uncompressed = data.toString();
  console.log("Adding "+uncompressed+" to buffer..")
  buffer.push(uncompressed);
  //ws.write(uncompressed); // I've also tried this but it does not work
}).on('end', function() {
  const ws=fs.createWriteStream(null,{fd:fd})
    ws.on('close',() => {
    console.log("Entering ws on finish...");
    cb(200, JSON.stringify({error : null, "written bytes":ws.bytesWritten})+'\n')
  })
  console.log("buffer: '"+buffer+"'");
  ws.write(buffer.join(""));
  ws.end();
}).on('error',function(e) {
  console.log("error: "+e);
})

req.pipe(gunzip);

【讨论】:

    猜你喜欢
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    • 2020-06-28
    相关资源
    最近更新 更多