2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

node-redで画像をhttp postで中継送信

Last updated at Posted at 2021-05-04

1. はじめに

Node-Redが中継役として、http postされた画像を別サーバにhttp postする方法についてまとめました。
この方法を対向系を作成しながら模索した記事は別にしています。

2. 全体の概要

想定しているのは、カメラノードからhttp post でアップロードされた画像をラズパイが一旦引き取り、クラウド側へhttp postでアップロードするという構成です。次の図のような構成です。

diagramOverall.png

カメラノードとしてM5Cameraを想定しています。M5Cameraがhttp postする方法は、こちらに挙げています。 M5CameraはIoTでいうところのエッジですので、いきなりクラウド側に上げる役割を持たせるのは、能力的にも、開発工数的にも、不安があります。その点、ラズパイは、パワーがあり、node-redで開発も容易ですので、フォグコンピューティングとしての役割を持たせるのがとても都合が良いです。

クラウド側も最近は、Node-Redが動くサーバがほとんどです。そうなると、今回の内容はそのままクラウド側にも流用できそうですが、今回は、旧来のCGIを対象として考えてみます。

3. フローの構築

3.1. 全体

全体のフローは次の通りです。

01b.png

このフローのjsonは次です。(三角マークをクリックして展開して利用してください)

RelayImagehttpPost.json
[
    {
        "id": "46a5b4e9.1028e4",
        "type": "tab",
        "label": "フロー 2",
        "disabled": false,
        "info": ""
    },
    {
        "id": "e4365738.d8df28",
        "type": "http in",
        "z": "46a5b4e9.1028e4",
        "name": "",
        "url": "/mypost01",
        "method": "post",
        "upload": true,
        "swaggerDoc": "",
        "x": 120,
        "y": 120,
        "wires": [
            [
                "39c6a8ed.47b6",
                "99b3be79.f601c8"
            ]
        ]
    },
    {
        "id": "7e14122.70cf86c",
        "type": "http response",
        "z": "46a5b4e9.1028e4",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 460,
        "y": 60,
        "wires": []
    },
    {
        "id": "39c6a8ed.47b6",
        "type": "template",
        "z": "46a5b4e9.1028e4",
        "name": "",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "received",
        "output": "str",
        "x": 310,
        "y": 60,
        "wires": [
            [
                "7e14122.70cf86c"
            ]
        ]
    },
    {
        "id": "a06d87ec.8581c8",
        "type": "function",
        "z": "46a5b4e9.1028e4",
        "name": "wrap",
        "func": "//let myb64 = msg.payload.toString('base64');\n\nlet mymsg2={};\n\nmymsg2.headers = {\n    \"Content-Type\": \"multipart/form-data; boundary=------------------------1234567890987654\"\n}\n\nmymsg2.payload = '--------------------------1234567890987654\\r\\n'+\n'Content-Disposition: form-data; name=\"imagefile\"; filename=\"10x10.jpg\"\\r\\n'+\n'Content-Type: image/jpeg\\r\\n'+\n'Content-Transfer-Encoding: base64\\r\\n'+\n'\\r\\n'+\nmsg.payload +\n'\\r\\n'+\n'--------------------------1234567890987654--\\r\\n';\n\n\nlet mymsg1={};\n\nmymsg1.headers = {\n    \"Content-Type\": \"multipart/form-data\"\n}\n\nmymsg1.payload = \n{\n    \"imagefile\": {\n        \"value\": msg.payload,\n        \"options\": {\n            \"filename\": \"FILENAME\"\n        }\n    }\n};\n\nreturn(mymsg1);\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 490,
        "y": 120,
        "wires": [
            [
                "b29cd1d6.842e9"
            ]
        ]
    },
    {
        "id": "b29cd1d6.842e9",
        "type": "http request",
        "z": "46a5b4e9.1028e4",
        "name": "",
        "method": "POST",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "localhost:1880/cgi-bin/imgpost01.cgi",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 690,
        "y": 120,
        "wires": [
            []
        ]
    },
    {
        "id": "99b3be79.f601c8",
        "type": "change",
        "z": "46a5b4e9.1028e4",
        "name": "pick file",
        "rules": [
            {
                "t": "move",
                "p": "req.files[0].buffer",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 310,
        "y": 120,
        "wires": [
            [
                "682c93b2.3ecacc",
                "a06d87ec.8581c8"
            ]
        ]
    },
    {
        "id": "682c93b2.3ecacc",
        "type": "file",
        "z": "46a5b4e9.1028e4",
        "name": "",
        "filename": "img01.jpg",
        "appendNewline": true,
        "createDir": false,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 480,
        "y": 200,
        "wires": [
            []
        ]
    }
]

3.2. 各ノードの設定

では、左のノードから設定を説明します。

3.2.1. http inノード

http inノードを編集します。メソッドを POST にして、ファイルのアップロードにチェックを入れます。今回は、カメラノードから送付するURLは、mypost01という名前にしてあります。ここは適宜変更してください(カメラノードのプログラムと一致させます)。

02.png

3.2.2. Templateノード

postした側への返答をテンプレートノードで作成します。文面は何でも良いです。

03.png

3.2.3. HTTP-Responseノード

コード200を返すのがhttp responseです。特に何も設定する必要がありません。

04.png

3.2.4. changeノード

ここからが、中継としての処理になります。

changeノードで、http inで受け取った画像ファイルを取り出し、このデータ列をpayloadとして後続のノードへ渡します。

05.png

なお、このchangeノードの役割が、http postで受け取ったファイルの取り扱いとして重要です。
http-inノードは、POSTメソッドでファイルを受信すると、ファイルpayloadではなく、req.files[]にその情報が入ります。ファイル自体は、bufferに配列として格納されます。
フローよりもプログラム志向な方は、このchangeノードと等価な動きをする、次のスクリプトをfunctionノードで書いた方が馴染みやすいかもしれません。

let mymsg={};
mymsg.payload=msg.req.files[0].buffer;
return mymsg;

3.2.6. Functionノード

今回の肝、functionノードでファイルを指定された構造で包みます。 http-responseのヘルプに書いてある内容そのままです。

07b.png

内容は次の通りです。相手のCGIで抽出する名前とキー名を一致させる必要があります。今回は、"imagefile"としています。なお、参考にしたのは次のページです。 https://discourse.nodered.org/t/http-post-image-image/32669/2

let mymsg1={};

mymsg1.headers = {
    "Content-Type": "multipart/form-data"
}

mymsg1.payload = 
{
    "imagefile": {
        "value": msg.payload,
        "options": {
            "filename": "FILENAME"
        }
    }
};

return(mymsg1);

3.2.7. HTTP-Requestノード

最後に、http requestノードで、payloadに画像とともに載せた情報をサーバに渡します。サーバのURLを記述します。ここでは、サンプルとして、このホスト内のサービスに投げています。

08.png

4. 重要な点

node-redで画像をhttp postで受信し、http postで送信する場合の重要な点を挙げます。

  • 送信では送信内容を指定された構造で包みます。
  • バイナリのまま送信できます。(Base64にする必要がありません)
  • 受信のファイルは、msg.req.files[0].bufferに格納されています。

これらを知っていれば、戸惑う事は無いと思います。

5. おわりに

今回は、Node-Redで画像をhttp postで中継送信するためのフローを挙げました。 冒頭でM5Cameraは能力的に不安があるという書き方をしましたが、実際は問題無いと思います。しかし、開発工数的には、圧倒的にラズパイの方に歩があると思います。
これを模索するために、色々と試しましたので、それについても記事として上げました。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?