0

I am reading a growing file in nodejs. Using below code in my app.js.

app.post('/readfile',function (req,res) {   
    var fullfilename = req.body.filepath+"\\"+req.body.filename;
    var bite_size = 256;
    var readbytes = 0;
    var file;

    fs.open(fullfilename, 'r', function(err, fd) {
        file = fd;      
        if(err){console.log(err); throw err; return;};
        var mybuff;
        var func = (function readsome() {               
        var stats = fs.fstatSync(fd); // yes sometimes async does not make sense!
                if(stats.size<readbytes+1) {                    
                    setTimeout(readsome, 1000);
                }
                else {
                    fs.read(fd, new Buffer(bite_size), 0, bite_size, readbytes, function (err, bytecount, buff) {
                    //console.log(buff.toString('utf-8', 0, bytecount));
                    res.json(buff.toString('utf-8', 0, bytecount));
                    readbytes+=bytecount;
                    process.nextTick(readsome);
                    });
                };          
        })();           
    }); 
}); 

And calling this in html like below ,

var myApp= angular.module("myApp", [])
myApp.controller('Ctrl1', function ($scope, $http,$q) {
        var FileName = "test.txt"
        var obj = {"filepath" : 'D:\\Temp', "filename" : FileName};

        $http({
                url: '/readTfile',
                method: "POST",
                data: JSON.stringify(obj)
                //timeout: canceller.promise,
                //headers: {'Content-Type': 'application/json','charset' : 'utf-8'}
                }).success(function(result) {               
                $scope.myfiledata = result;                     
                }).error(function(data, status) {
                console.log(data);
                }); 
});

This is working fine when i put this app.js code in a separate file (readfile.js) but when i put in app.js it gives error.

_http_outgoing.js:357
    throw new Error('Can\'t set headers after they are sent.');
    ^
Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:357:11)
    at ServerResponse.header (D:\myapp\node_modules\express\lib\response.js:725:10)
    at ServerResponse.send (D:\myapp\node_modules\express\lib\response.js:170:12)
    at ServerResponse.json (D:\myapp\node_modules\express\lib\response.js:256:15)
    at D:\myapp\app.js:130:10
    at FSReqWrap.wrapper [as oncomplete] (fs.js:682:17)
[nodemon] app crashed - waiting for file changes before starting...

Please help to find where is the mistake and what to be changed. Secondly i want to stop this call on button click, how can i do that ?

usersam
  • 1,125
  • 4
  • 27
  • 54
  • As an aside, I suggest reading up on the difference between `nextTick` and `setImmediate` https://stackoverflow.com/questions/15349733/setimmediate-vs-nexttick I suspect you might be better of with `setImmediate`. – skirtle Sep 11 '17 at 15:38

2 Answers2

0

This is just a guess, but, did you remove the old code, before adding the code in app.js ?

Maybe your /readfile route is added by both app.js and in the separate file, so that first route sends out the response, and when the second route starts to do the same, it gets the error of response already been sent.

Rainer Plumer
  • 3,693
  • 2
  • 24
  • 42
0

You can only call res.json once on a request. It sets the relevant headers, JSON encodes the data, sends it as the response and then ends the request.

If you just want to write some of the data you can use write: https://nodejs.org/api/http.html#http_response_write_chunk_encoding_callback

Or maybe you could using piping to do it all for you instead?

var readStream = fs.createReadStream(fullfilename);
readStream.pipe(res);
skirtle
  • 27,868
  • 4
  • 42
  • 57
  • Thanks @skirtle. First i created api with "createReadStream" which worked well with static file but i want to capture new lines added also. I used fs.watch for this, and fs.read so that i can put offset as i need data in chunk. Is it possible to do the same with createReadStream ? any working example would be great help. – usersam Sep 11 '17 at 16:17