Repository: node-red/node-red (js)

Issue:
File nodes output error when number is specified as filename
### Current Behavior

File nodes only support string type as the file name in `msg.` and JSONata expression.
Therefore, users often encounter the following error when using timestamp for filename.

<img width="1357" alt="Screenshot 2023-08-06 at 20 49 52" src="https://github.com/node-red/node-red/assets/20310935/16de5aa0-5df7-482c-825c-e5fd6f23f820">

I thought that file nodes should support not only string but also number and boolean as filename.

### Expected Behavior

The file node stores the data in the file that has numbers as its filename.

### Steps To Reproduce

1. Put inject node
2. Put write file node
3. Open the write file node property and specify `msg.payload` as a filename.
4. Connect nodes by wire
5. Click the deploy button
6. Click the button on inject node.

### Example flow

```
[{"id":"7a37368e4713e725","type":"inject","z":"48e50bbaa6a50483","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":40,"wires":[["b3a0d920dedc5559"]]},{"id":"b3a0d920dedc5559","type":"file","z":"48e50bbaa6a50483","name":"","filename":"payload","filenameType":"msg","appendNewline":false,"createDir":false,"overwriteFile":"false","encoding":"none","x":280,"y":120,"wires":[[]]}]
```


### Environment

- Node-RED version: v3.1.0-beta.4
- Node.js version: v20.2.0
- npm version: v9.6.6
- Platform/OS: macOS Ventura 13.4.1 (c) on MacBook Air (M1, 2020)
- Browser: 115.0.5790.170 (Official Build) (arm64)

Pull request:
Fix handling in file nodes when number is specified as file name
- [x] Bugfix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)

## Proposed changes
Fixed #4266.

## Checklist
- [x] I have read the [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
- [ ] For non-bugfix PRs, I have discussed this change on the forum/slack team.
- [x] I have run `grunt` to verify the unit tests pass
- [x] I have added suitable unit tests to cover the new/changed functionality

Patch:
diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.js b/packages/node_modules/@node-red/nodes/core/storage/10-file.js
index 601f5b46d..fea8c490e 100644
--- a/packages/node_modules/@node-red/nodes/core/storage/10-file.js
+++ b/packages/node_modules/@node-red/nodes/core/storage/10-file.js
@@ -68,6 +68,9 @@ module.exports = function(RED) {
                     node.error(err,msg);
                     return done();
                 } else {
+                    if (typeof value !== 'string' && value !== null && value !== undefined) {
+                        value = value.toString();
+                    }
                     processMsg2(msg,nodeSend,value,done);
                 }
             });
@@ -278,7 +281,6 @@ module.exports = function(RED) {
     }
     RED.nodes.registerType("file",FileNode);
 
-
     function FileInNode(n) {
         // Read a file
         RED.nodes.createNode(this,n);
@@ -314,6 +316,9 @@ module.exports = function(RED) {
                     node.error(err,msg);
                     return done();
                 } else {
+                    if (typeof value !== 'string' && value !== null && value !== undefined) {
+                        value = value.toString();
+                    }
                     processMsg2(msg, nodeSend, (value || "").replace(/\t|\r|\n/g,''), nodeDone);
                 }
             });


Test patch:
diff --git a/test/nodes/core/storage/10-file_spec.js b/test/nodes/core/storage/10-file_spec.js
index 584aaffd5..57e32985c 100644
--- a/test/nodes/core/storage/10-file_spec.js
+++ b/test/nodes/core/storage/10-file_spec.js
@@ -121,7 +121,6 @@ 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"}];
@@ -145,7 +144,6 @@ describe('file Nodes', function() {
             });
         });
 
-
         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"}];
@@ -447,6 +445,31 @@ describe('file Nodes', function() {
                 n1.receive({payload:"typedInput", _user_specified_filename:fileToTest});
             });
         });
+
+        it('should support number in msg._user_specified_filename', function (done) {
+            var flow = [{id:"fileNode1", type:"file", filename:"_user_specified_filename", filenameType:"msg", name:"fileNode", "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 fileToTest = path.join(resourcesDir, "123");
+                        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", _user_specified_filename: 123});
+            });
+        });
+
         it('should use env.TEST_FILE set in nodes typedInput', function(done) {
             var flow = [{id:"fileNode1", type:"file", filename:"TEST_FILE", filenameType: "env", name: "fileNode", "appendNewline":true, "overwriteFile":true, wires: [["helperNode1"]]},
                         {id:"helperNode1", type:"helper"}];