HTML code to transfer images to Node-Red http-request node

Hi, I need to transfer images to Node-red, found many examples on how to handle the image once it arrives but no example on the html/JavaScript that would post a local image to Node-Red.
Where can I find such example code?
Thanks
Assistance welcome.

There are several examples around the forum.

You need to be searching for the likes of post image endpoint

Here is a post that (amongst other things) posts an image from front end (browser) to back end (node-red) : HTTP endpoint for image payloads - #4 by Steve-Mcl

Dear Steve, thanks for the link but the Node-Red side I already have, as you say there are examples in this forum.
What I am looking for is the client html side of it.

Regards

From that post...

Did you import the flow & look in the template?

Hi, Currently I have a flow that accepts an URL for the image. But that method forces me to first upload the image to an FTP server then call Node-Red node-red-contrib-custom-port http-in node.
The edit-image node I use can also handle the image itself so I would not need to have an FTP for that purpose.
So, the idea is to post the image directly to Node-Red node-red-contrib-custom-port http-in node.
So I did not import the flow, I intend to test the provided fetch API to post the image directly to my current flow.

Thanks

Steve, I had Apache with SSL (https) and the fetch was to be executed against Node-red (same server) that was http only. Then I had the message: net::ERR_SSL_PROTOCOL_ERROR

So I went on to sort this problem out and install SSL on Node-Red as well.
Now I have SSL on Node-Red as well but still the same error message.

The application that submits the URL instead of the image posts the request to the same Node-Red server and even kept working after Node-Red was upgraded to use my SSL certificate.

May be Node-Red does not support fetch... is it possible?
Is there a way to post the image without using fetch?
Thanks

is that just a message from you browser because its a self signed certificate ?
have you tried Firefox ? .. it usually warns you but you can proceed to the page unlike Chrome that is a bit more strict ?

I worked on an example to demonstrate Multiple File upload and saving them to a path with the File write node. I used the core node Http in but maybe you can replicate it with your node-red-contrib-custom-port http-in node.

[{"id":"57de1f9aea908186","type":"http in","z":"54efb553244c241f","name":"","url":"/upload","method":"get","upload":true,"swaggerDoc":"","x":370,"y":2980,"wires":[["bc02a644eef2d95b"]]},{"id":"bc02a644eef2d95b","type":"template","z":"54efb553244c241f","name":"","field":"payload","fieldType":"msg","format":"html","syntax":"plain","template":"<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />\n\n  <style>\n    * {\n      box-sizing: border-box;\n      font: inherit;\n    }\n\n    html {\n      font-size: 20px;\n      font-family: sans-serif;\n      margin: 0;\n    }\n\n    body {\n      margin: 0;\n    }\n\n    header {\n      padding: 1rem 3rem;\n      background-color: coral;\n      color: white;\n      border-bottom: 1px solid #000;\n    }\n\n    :is(main, footer) {\n      padding: 1rem 3rem;\n    }\n\n    header h1 {\n      font-size: 2rem;\n    }\n\n    form {\n      padding: 0 4rem;\n    }\n\n    .hidden {\n      opacity: 0;\n      height: 0;\n      line-height: 0;\n      overflow: hidden;\n      padding: 0;\n      margin: 0;\n    }\n\n    footer img {\n      width: 300px;\n    }\n  </style>\n\n  <title>File and FileList</title>\n</head>\n\n<body>\n  <header>\n    <h1>File and FileList (and fetch too)</h1>\n  </header>\n  <main>\n    <h2>Gather Your Files</h2>\n    <form name=\"myform\" id=\"myform\" action=\"#\">\n      <p>\n        <label>Pick Files</label>\n        <input\n            type=\"file\"\n            id=\"inputFile\"\n            multiple\n            accept=\".jpg,.png\"\n          />\n      </p>\n      <!-- \n          text/html,.html,text/xml,.xml\n          text/css,.css\n          application/json,.json,text/json\n          image/*,.png,.jpg,.gif,.webp,image/jpeg,image/gif,image/webp,image/png  \n        -->\n\n    </form>\n  </main>\n\n  <script>\n    document.addEventListener('DOMContentLoaded', () => {\n    document.getElementById('inputFile').addEventListener('change', filesPicked);\n\n\n});\n\nfunction filesPicked(ev) {\n  //any time one or more files are picked in the file picker dialog\n  let input = ev.target;\n  let files = input.files;\n  console.log({ files });\n  if (files.length > 0) {\n\n    //upload a file or file(s) to a web server/api\n    let url = 'https://192.168.0.7:1880/upload';\n    let fd = new FormData();\n\n    for (let i = 0, len = files.length; i < len; i++) {\n      fd.append(`files-${i}`, files[i], files[i].name);\n    }\n    let request = new Request(url, {\n      body: fd,\n      // headers: h,\n      mode: 'no-cors',\n      method: 'POST',\n    });\n\n    fetch(request)\n      .then(response => {\n        console.log(response.status, response.statusText);\n        return response.json()\n      })\n      .then( data => console.log(data))\n      .catch(error => console.error('Error:', error) );\n  }\n}\n\n  </script>\n</body>\n\n</html>","output":"str","x":620,"y":2980,"wires":[["50245a36d9e7188e"]]},{"id":"50245a36d9e7188e","type":"http response","z":"54efb553244c241f","name":"","statusCode":"","headers":{},"x":850,"y":2980,"wires":[]},{"id":"2e007b56569f311a","type":"http in","z":"54efb553244c241f","name":"","url":"/upload","method":"post","upload":true,"swaggerDoc":"","x":370,"y":3140,"wires":[["0c6ec466dea68948","acc027b5259d0881"]]},{"id":"cbf6795de952fb70","type":"http response","z":"54efb553244c241f","name":"","statusCode":"","headers":{"content-type":"application/json"},"x":850,"y":3120,"wires":[]},{"id":"0c6ec466dea68948","type":"function","z":"54efb553244c241f","name":"process files","func":"let files = msg.req.files;\n\nfiles.forEach(file => {\n\n    let obj = {\n        filename: `c:/Share/images/${file.originalname}`, // your folder\n        payload: file.buffer\n    }\n\n    node.send([null, obj])  // 2nd output - send each file to File out node\n\n})\n\n\n\nmsg.payload = { message: \"Thank you for your upload\" }\nmsg.statusCode = 200;\n// 1st output - to Http Response node\nreturn [msg, null];","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":3140,"wires":[["cbf6795de952fb70"],["2e701ea54d363749","7b1f78bc80bde15a"]]},{"id":"acc027b5259d0881","type":"debug","z":"54efb553244c241f","name":"debug 1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":435,"y":3200,"wires":[],"l":false},{"id":"2e701ea54d363749","type":"file","z":"54efb553244c241f","name":"","filename":"filename","filenameType":"msg","appendNewline":false,"createDir":true,"overwriteFile":"true","encoding":"none","x":860,"y":3180,"wires":[[]]},{"id":"7b1f78bc80bde15a","type":"debug","z":"54efb553244c241f","name":"debug 2","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":645,"y":3200,"wires":[],"l":false},{"id":"708d7c7dabdf1f9d","type":"comment","z":"54efb553244c241f","name":"GET /upload Serving the html ","info":"","x":420,"y":2920,"wires":[]},{"id":"4eda36f71f1856c7","type":"comment","z":"54efb553244c241f","name":"POST /upload saving the images","info":"","x":430,"y":3080,"wires":[]}]

ps1. it would be better if you shared your flow
ps2. for the example you need to change the server IP in the Template and the folder path in the Function node.
ps3. credit for the front-end page goes to (link)

Hi, my certificate is not self signed.
To test the flow below I use
https://alprbr.com:30300/test

image

[
    {
        "id": "255a1b55f427b632",
        "type": "node-red-contrib-http-custom-port",
        "z": "bbdfa920e9d355f5",
        "name": "",
        "url": "/test",
        "method": "get",
        "upload": true,
        "swaggerDoc": "",
        "port": "30300",
        "x": 220,
        "y": 160,
        "wires": [
            [
                "a28901b41cdebf7a"
            ]
        ]
    },
    {
        "id": "e03075e486ebb69c",
        "type": "http response",
        "z": "bbdfa920e9d355f5",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 490,
        "y": 300,
        "wires": []
    },
    {
        "id": "14a777b8fa7470d4",
        "type": "debug",
        "z": "bbdfa920e9d355f5",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 490,
        "y": 180,
        "wires": []
    },
    {
        "id": "a28901b41cdebf7a",
        "type": "template",
        "z": "bbdfa920e9d355f5",
        "name": "",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "<html>\n    <head>\n    <title>Hello</title>\n    </head>\n    <h1>Hello</h1>\n</html>\n",
        "output": "str",
        "x": 320,
        "y": 240,
        "wires": [
            [
                "e03075e486ebb69c",
                "14a777b8fa7470d4"
            ]
        ]
    }
]

TCP 30300 is open on the firewall.
Apache works ok with https
Node-Red console also works now via https.

Thanks

Problem solved by using Node-Red as http server and stop using Apache for image upload to my API.
It seems that http nodes do not support SSL even when SSL is installed on Node-Red.

Thanks

1 Like

yea .. from the description of node-red-contrib-http-custom-port it seems that its spinning its own express server to be able to serve on a different port and the security settings of Node-red do not apply for its endpoints.

Glad you got it working entirely in NR .. be sure to add additional checks and security if you planning to have it open to the internet

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.