mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	File node: Add fileWorkingDirectory to customise how relative paths are resolved
This commit is contained in:
		@@ -51,6 +51,10 @@ module.exports = function(RED) {
 | 
			
		||||
 | 
			
		||||
        function processMsg(msg,nodeSend, done) {
 | 
			
		||||
            var filename = node.filename || msg.filename || "";
 | 
			
		||||
            var fullFilename = filename;
 | 
			
		||||
            if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
 | 
			
		||||
                fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
 | 
			
		||||
            }
 | 
			
		||||
            if ((!node.filename) && (!node.tout)) {
 | 
			
		||||
                node.tout = setTimeout(function() {
 | 
			
		||||
                    node.status({fill:"grey",shape:"dot",text:filename});
 | 
			
		||||
@@ -62,7 +66,7 @@ module.exports = function(RED) {
 | 
			
		||||
                node.warn(RED._("file.errors.nofilename"));
 | 
			
		||||
                done();
 | 
			
		||||
            } else if (node.overwriteFile === "delete") {
 | 
			
		||||
                fs.unlink(filename, function (err) {
 | 
			
		||||
                fs.unlink(fullFilename, function (err) {
 | 
			
		||||
                    if (err) {
 | 
			
		||||
                        node.error(RED._("file.errors.deletefail",{error:err.toString()}),msg);
 | 
			
		||||
                    } else {
 | 
			
		||||
@@ -74,7 +78,7 @@ module.exports = function(RED) {
 | 
			
		||||
                    done();
 | 
			
		||||
                });
 | 
			
		||||
            } else if (msg.hasOwnProperty("payload") && (typeof msg.payload !== "undefined")) {
 | 
			
		||||
                var dir = path.dirname(filename);
 | 
			
		||||
                var dir = path.dirname(fullFilename);
 | 
			
		||||
                if (node.createDir) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        fs.ensureDirSync(dir);
 | 
			
		||||
@@ -94,7 +98,7 @@ module.exports = function(RED) {
 | 
			
		||||
                if ((node.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; }
 | 
			
		||||
                var buf = encode(data, node.encoding);
 | 
			
		||||
                if (node.overwriteFile === "true") {
 | 
			
		||||
                    var wstream = fs.createWriteStream(filename, { encoding:'binary', flags:'w', autoClose:true });
 | 
			
		||||
                    var wstream = fs.createWriteStream(fullFilename, { encoding:'binary', flags:'w', autoClose:true });
 | 
			
		||||
                    node.wstream = wstream;
 | 
			
		||||
                    wstream.on("error", function(err) {
 | 
			
		||||
                        node.error(RED._("file.errors.writefail",{error:err.toString()}),msg);
 | 
			
		||||
@@ -116,7 +120,7 @@ module.exports = function(RED) {
 | 
			
		||||
                        // of the file. Check the file hasn't been deleted
 | 
			
		||||
                        // or deleted and recreated.
 | 
			
		||||
                        try {
 | 
			
		||||
                            var stat = fs.statSync(filename);
 | 
			
		||||
                            var stat = fs.statSync(fullFilename);
 | 
			
		||||
                            // File exists - check the inode matches
 | 
			
		||||
                            if (stat.ino !== node.wstreamIno) {
 | 
			
		||||
                                // The file has been recreated. Close the current
 | 
			
		||||
@@ -135,10 +139,10 @@ module.exports = function(RED) {
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    if (recreateStream) {
 | 
			
		||||
                        node.wstream = fs.createWriteStream(filename, { encoding:'binary', flags:'a', autoClose:true });
 | 
			
		||||
                        node.wstream = fs.createWriteStream(fullFilename, { encoding:'binary', flags:'a', autoClose:true });
 | 
			
		||||
                        node.wstream.on("open", function(fd) {
 | 
			
		||||
                            try {
 | 
			
		||||
                                var stat = fs.statSync(filename);
 | 
			
		||||
                                var stat = fs.statSync(fullFilename);
 | 
			
		||||
                                node.wstreamIno = stat.ino;
 | 
			
		||||
                            } catch(err) {
 | 
			
		||||
                            }
 | 
			
		||||
@@ -258,6 +262,10 @@ module.exports = function(RED) {
 | 
			
		||||
 | 
			
		||||
        this.on("input",function(msg, nodeSend, nodeDone) {
 | 
			
		||||
            var filename = (node.filename || msg.filename || "").replace(/\t|\r|\n/g,'');
 | 
			
		||||
            var fullFilename = filename;
 | 
			
		||||
            if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
 | 
			
		||||
                fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
 | 
			
		||||
            }
 | 
			
		||||
            if (!node.filename) {
 | 
			
		||||
                node.status({fill:"grey",shape:"dot",text:filename});
 | 
			
		||||
            }
 | 
			
		||||
@@ -279,7 +287,7 @@ module.exports = function(RED) {
 | 
			
		||||
                var hwm;
 | 
			
		||||
                var getout = false;
 | 
			
		||||
 | 
			
		||||
                var rs = fs.createReadStream(filename)
 | 
			
		||||
                var rs = fs.createReadStream(fullFilename)
 | 
			
		||||
                    .on('readable', function () {
 | 
			
		||||
                        var chunk;
 | 
			
		||||
                        var hwm = rs._readableState.highWaterMark;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								packages/node_modules/node-red/settings.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								packages/node_modules/node-red/settings.js
									
									
									
									
										vendored
									
									
								
							@@ -46,6 +46,10 @@ module.exports = {
 | 
			
		||||
    //  defaults to 10Mb
 | 
			
		||||
    //execMaxBufferSize: 10000000,
 | 
			
		||||
 | 
			
		||||
    // The working directory to handle relative file paths from within the File nodes
 | 
			
		||||
    //  defaults to the working directory of the Node-RED process.
 | 
			
		||||
    //fileWorkingDirectory: "",
 | 
			
		||||
    
 | 
			
		||||
    // The maximum length, in characters, of any message sent to the debug sidebar tab
 | 
			
		||||
    debugMaxLength: 1000,
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ var sinon = require("sinon");
 | 
			
		||||
var iconv = require("iconv-lite");
 | 
			
		||||
var fileNode = require("nr-test-utils").require("@node-red/nodes/core/storage/10-file.js");
 | 
			
		||||
var helper = require("node-red-node-test-helper");
 | 
			
		||||
var RED = require("nr-test-utils").require("node-red/lib/red");
 | 
			
		||||
 | 
			
		||||
describe('file Nodes', function() {
 | 
			
		||||
 | 
			
		||||
@@ -41,8 +42,9 @@ describe('file Nodes', function() {
 | 
			
		||||
 | 
			
		||||
    describe('file out Node', function() {
 | 
			
		||||
 | 
			
		||||
        var relativePathToFile = "50-file-test-file.txt";
 | 
			
		||||
        var resourcesDir = path.join(__dirname,"..","..","..","resources");
 | 
			
		||||
        var fileToTest = path.join(resourcesDir,"50-file-test-file.txt");
 | 
			
		||||
        var fileToTest = path.join(resourcesDir,relativePathToFile);
 | 
			
		||||
        var wait = 250;
 | 
			
		||||
 | 
			
		||||
        beforeEach(function(done) {
 | 
			
		||||
@@ -51,6 +53,7 @@ describe('file Nodes', function() {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        afterEach(function(done) {
 | 
			
		||||
            delete RED.settings.fileWorkingDirectory;
 | 
			
		||||
            fs.removeSync(path.join(resourcesDir,"file-out-node"));
 | 
			
		||||
            helper.unload().then(function() {
 | 
			
		||||
                //fs.unlinkSync(fileToTest);
 | 
			
		||||
@@ -94,6 +97,30 @@ describe('file Nodes', function() {
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should write to a file using RED.settings.fileWorkingDirectory', function(done) {
 | 
			
		||||
            var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":relativePathToFile, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
 | 
			
		||||
                        {id:"helperNode1", type:"helper"}];
 | 
			
		||||
            helper.load(fileNode, flow, function() {
 | 
			
		||||
                RED.settings.fileWorkingDirectory = resourcesDir;
 | 
			
		||||
                var n1 = helper.getNode("fileNode1");
 | 
			
		||||
                var n2 = helper.getNode("helperNode1");
 | 
			
		||||
                n2.on("input", function(msg) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        var f = fs.readFileSync(fileToTest);
 | 
			
		||||
                        f.should.have.length(4);
 | 
			
		||||
                        fs.unlinkSync(fileToTest);
 | 
			
		||||
                        msg.should.have.property("payload", "test");
 | 
			
		||||
                        done();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (e) {
 | 
			
		||||
                        done(e);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                n1.receive({payload:"test"});
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        it('should write multi-byte string to a file', function(done) {
 | 
			
		||||
            var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
 | 
			
		||||
                        {id:"helperNode1", type:"helper"}];
 | 
			
		||||
@@ -1036,9 +1063,10 @@ describe('file Nodes', function() {
 | 
			
		||||
 | 
			
		||||
    describe('file in Node', function() {
 | 
			
		||||
 | 
			
		||||
        var relativePathToFile = "50-file-test-file.txt";
 | 
			
		||||
        var resourcesDir = path.join(__dirname,"..","..","..","resources");
 | 
			
		||||
        var fileToTest = path.join(resourcesDir,"50-file-test-file.txt");
 | 
			
		||||
        var fileToTest2 = "\t"+path.join(resourcesDir,"50-file-test-file.txt")+"\r\n";
 | 
			
		||||
        var fileToTest = path.join(resourcesDir,relativePathToFile);
 | 
			
		||||
        var fileToTest2 = "\t"+path.join(resourcesDir,relativePathToFile)+"\r\n";
 | 
			
		||||
        var wait = 150;
 | 
			
		||||
 | 
			
		||||
        beforeEach(function(done) {
 | 
			
		||||
@@ -1047,6 +1075,7 @@ describe('file Nodes', function() {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        afterEach(function(done) {
 | 
			
		||||
            delete RED.settings.fileWorkingDirectory;
 | 
			
		||||
            helper.unload().then(function() {
 | 
			
		||||
                fs.unlinkSync(fileToTest);
 | 
			
		||||
                helper.stopServer(done);
 | 
			
		||||
@@ -1100,6 +1129,30 @@ describe('file Nodes', function() {
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        it('should read in a file using fileWorkingDirectory to set cwd', function(done) {
 | 
			
		||||
            var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":relativePathToFile, "format":"utf8", wires:[["n2"]]},
 | 
			
		||||
                        {id:"n2", type:"helper"}];
 | 
			
		||||
            helper.load(fileNode, flow, function() {
 | 
			
		||||
                RED.settings.fileWorkingDirectory = resourcesDir;
 | 
			
		||||
                var n1 = helper.getNode("fileInNode1");
 | 
			
		||||
                var n2 = helper.getNode("n2");
 | 
			
		||||
                n2.on("input", function(msg) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        msg.should.have.property('payload');
 | 
			
		||||
                        msg.payload.should.be.a.String();
 | 
			
		||||
                        msg.payload.should.have.length(40)
 | 
			
		||||
                        msg.payload.should.equal("File message line 1\nFile message line 2\n");
 | 
			
		||||
                        done();
 | 
			
		||||
                    } catch(err) {
 | 
			
		||||
                        done(err);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                n1.receive({payload:""});
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        it('should read in a file ending in cr and output a utf8 string', function(done) {
 | 
			
		||||
            var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":fileToTest2, "format":"utf8", wires:[["n2"]]},
 | 
			
		||||
                {id:"n2", type:"helper"}];
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user