這裡提供一個使用 Node-RED 透過 HTTP 請求送出與接收檔案的示範流程。以下是流程的概述:
- 送出檔案群組: - 使用 inject節點觸發流程。
- function節點用於格式化標頭和 payload。
- http request節點透過 POST 方法將檔案送至指定的 URL(- http://localhost:1881/files)。
- debug節點用於顯示送出請求的相關資訊。
 
- 接收檔案群組: - http in節點設定接收檔案的 URL(/files)和使用 POST 方法。
- debug節點用於顯示接收請求的相關資訊。
- change節點用於設定回應的 payload 為 "okay"。
- http response節點用於回應 HTTP 請求。
- file節點用於將接收到的檔案寫入指定位置。
- debug節點用於顯示接收到的檔案內容。
 
在使用這個示範流程之前,你需要注意以下事項:
- 確保 Node-RED 已經安裝在你的系統上。
- 檔案送出的 URL 為 http://localhost:1881/files,你需要確保這個端點正確設定。
⚠️ 我是在同一台 PC 上測試,因此開了兩個 Node-RED (分別使用 1880、1881 Port)。
⚠️ 實際上使用只能傳輸 txt 文字檔,其餘格式的檔案似乎會出錯。
示範流程
[
    {
        "id": "07799332fb2cb315",
        "type": "tab",
        "label": "檔案送出與接收",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "61f1812e8e841da3",
        "type": "group",
        "z": "07799332fb2cb315",
        "name": "送出檔案",
        "style": {
            "label": true,
            "fill": "#e3f3d3",
            "fill-opacity": "0.2",
            "stroke": "#addb7b",
            "color": "#92d04f"
        },
        "nodes": [
            "6a156025.b1c9f",
            "9c0b2081.b1ac6",
            "85c748e8.2d1f88",
            "a4810d7a.f652a",
            "fd62708f.a560a"
        ],
        "x": 74,
        "y": 39,
        "w": 652,
        "h": 142
    },
    {
        "id": "2b6de2d20774e817",
        "type": "group",
        "z": "07799332fb2cb315",
        "name": "接收檔案",
        "style": {
            "label": true,
            "stroke": "#ff3f3f",
            "fill": "#ffbfbf",
            "fill-opacity": "0.32",
            "color": "#ff3f3f"
        },
        "nodes": [
            "c4f91df3.caef7",
            "ef0aaf76.2236e",
            "cc5a37cf.86c6d8",
            "c14febc0.522db8",
            "61d9c776d0fc2c5d",
            "d98f7e19f5c85c49",
            "8baa89ac7f9f9248"
        ],
        "x": 74,
        "y": 199,
        "w": 572,
        "h": 162
    },
    {
        "id": "6a156025.b1c9f",
        "type": "inject",
        "z": "07799332fb2cb315",
        "g": "61f1812e8e841da3",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 170,
        "y": 80,
        "wires": [
            [
                "fd62708f.a560a"
            ]
        ]
    },
    {
        "id": "9c0b2081.b1ac6",
        "type": "function",
        "z": "07799332fb2cb315",
        "g": "61f1812e8e841da3",
        "name": "格式化標頭和 payload",
        "func": "msg.headers = {\n    \"Content-Type\": \"multipart/form-data; boundary=------------------------d74496d66958873e\"\n}\n\n\nmsg.payload = '--------------------------d74496d66958873e\\r\\n'+\n'Content-Disposition: form-data; name=\"select\"\\r\\n'+\n'\\r\\n'+\n'true\\r\\n'+\n'--------------------------d74496d66958873e\\r\\n'+\n'Content-Disposition: form-data; name=\"print\"\\r\\n'+\n'\\r\\n'+\n'true\\r\\n'+\n'--------------------------d74496d66958873e\\r\\n'+\n'Content-Disposition: form-data; name=\"file\"; filename=\"'+msg.filename+'\"\\r\\n'+\n'Content-Type: application/octet-stream\\r\\n'+\n'\\r\\n'+\nmsg.payload+'\\r\\n'+\n'--------------------------d74496d66958873e--\\r\\n';\n\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 220,
        "y": 140,
        "wires": [
            [
                "85c748e8.2d1f88"
            ]
        ]
    },
    {
        "id": "85c748e8.2d1f88",
        "type": "http request",
        "z": "07799332fb2cb315",
        "g": "61f1812e8e841da3",
        "name": "",
        "method": "POST",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "http://localhost:1881/files",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 460,
        "y": 140,
        "wires": [
            [
                "a4810d7a.f652a"
            ]
        ]
    },
    {
        "id": "a4810d7a.f652a",
        "type": "debug",
        "z": "07799332fb2cb315",
        "g": "61f1812e8e841da3",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 610,
        "y": 140,
        "wires": []
    },
    {
        "id": "fd62708f.a560a",
        "type": "file in",
        "z": "07799332fb2cb315",
        "g": "61f1812e8e841da3",
        "name": "",
        "filename": "path\\to\\file.txt",
        "filenameType": "str",
        "format": "",
        "chunk": false,
        "sendError": false,
        "allProps": false,
        "x": 310,
        "y": 80,
        "wires": [
            [
                "9c0b2081.b1ac6"
            ]
        ]
    },
    {
        "id": "c4f91df3.caef7",
        "type": "http in",
        "z": "07799332fb2cb315",
        "g": "2b6de2d20774e817",
        "name": "",
        "url": "/files",
        "method": "post",
        "upload": true,
        "swaggerDoc": "",
        "x": 160,
        "y": 240,
        "wires": [
            [
                "cc5a37cf.86c6d8",
                "c14febc0.522db8",
                "d98f7e19f5c85c49"
            ]
        ]
    },
    {
        "id": "ef0aaf76.2236e",
        "type": "http response",
        "z": "07799332fb2cb315",
        "g": "2b6de2d20774e817",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 550,
        "y": 240,
        "wires": []
    },
    {
        "id": "cc5a37cf.86c6d8",
        "type": "debug",
        "z": "07799332fb2cb315",
        "g": "2b6de2d20774e817",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "req",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 360,
        "y": 280,
        "wires": []
    },
    {
        "id": "c14febc0.522db8",
        "type": "change",
        "z": "07799332fb2cb315",
        "g": "2b6de2d20774e817",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "okay",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 390,
        "y": 240,
        "wires": [
            [
                "ef0aaf76.2236e"
            ]
        ]
    },
    {
        "id": "61d9c776d0fc2c5d",
        "type": "file",
        "z": "07799332fb2cb315",
        "g": "2b6de2d20774e817",
        "name": "",
        "filename": "filename",
        "filenameType": "msg",
        "appendNewline": true,
        "createDir": false,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 420,
        "y": 320,
        "wires": [
            [
                "8baa89ac7f9f9248"
            ]
        ]
    },
    {
        "id": "d98f7e19f5c85c49",
        "type": "function",
        "z": "07799332fb2cb315",
        "g": "2b6de2d20774e817",
        "name": "接收檔案處理",
        "func": "msg.payload = msg.req.files[0].buffer;\nmsg.filename = \"/data/\" + msg.req.files[0].originalname;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 260,
        "y": 320,
        "wires": [
            [
                "61d9c776d0fc2c5d"
            ]
        ]
    },
    {
        "id": "8baa89ac7f9f9248",
        "type": "debug",
        "z": "07799332fb2cb315",
        "g": "2b6de2d20774e817",
        "name": "debug",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 550,
        "y": 320,
        "wires": []
    }
]
參考資源
https://flows.nodered.org/flow/cbf44e064b9406a1175a7e8d589f66ac