Como enviar imagens e dados para o Sankhya via API utilizando N8N

Depois de muita pesquisa e testes eis a solução que eu encontrei utilizando o N8N:

1- Envio do arquivo de imagem via Weebhook:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Enviar Arquivo</title>
</head>
<body>

  <h2>Enviar arquivo via Webhook</h2>

  <input type="file" id="arquivo" />
  <br><br>

  <button onclick="enviarArquivo()">Enviar</button>

  <pre id="resultado"></pre>

  <script src="enviar.js"></script>
</body>
</html>


function enviarArquivo() {
  const input = document.getElementById("arquivo");
  const resultado = document.getElementById("resultado");

  if (!input.files.length) {
    alert("Selecione um arquivo");
    return;
  }

  const file = input.files[0];
  const reader = new FileReader();

  reader.onload = function () {
    // remove "data:image/png;base64," ou similar
    const base64 = reader.result.split(",")[1];

    const payload = {
      nomeArquivo: file.name,
      tipo: file.type,
      tamanho: file.size,
      conteudoBase64: base64
    };

    fetch("https://WEEBHOOKLINK", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(payload)
    })  
    .then(res => res.text())
    .then(res => {
      resultado.textContent = "Enviado com sucesso!\n\n" + res;
    })
    .catch(err => {
      resultado.textContent = "Erro ao enviar:\n" + err;
    });
  };

  reader.readAsDataURL(file);
}



2- Recebe Imagem via Weebhook > Autentica o Gateway > Destaca o Bearer Token > Inclui dados e imagem via API:

{
  "name": "INCLUIR DADOS",
  "nodes": [
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.sandbox.sankhya.com.br/authenticate",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/x-www-form-urlencoded"
            },
            {
              "name": "Accept",
              "value": "application/x-www-form-urlencoded"
            },
            {
              "name": "X-Token",
              "value": "dc6af5b5-e78e-4e40-b8f6-710cb651eefd"
            }
          ]
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "grant_type",
              "value": "client_credentials"
            },
            {
              "name": "client_id",
              "value": "KEY GERADA NO SANKHYA"
            },
            {
              "name": "client_secret",
              "value": "KEY GERADA NO SANKHYA"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -304,
        -240
      ],
      "id": "1b5027bd-eab1-4f1a-ab36-ee4b614c3e86",
      "name": "Validação"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "b41550fd-d816-4171-aa47-2205c55fd3bf",
              "name": "token",
              "value": "={{ $json.access_token }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -112,
        -240
      ],
      "id": "df92bc05-d5cd-4065-bc8b-0ac6fa6bd7b4",
      "name": "Token"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "23055dd3-1e49-4d2f-ab04-7f28a4b356b7",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -560,
        -240
      ],
      "id": "6f2bd181-8b97-4b0d-9b71-ac3e0e197cc8",
      "name": "Webhook",
      "webhookId": "23055dd3-1e49-4d2f-ab04-7f28a4b356b7"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.sandbox.sankhya.com.br/gateway/v1/mge/service.sbr?serviceName=DatasetSP.save&outputType=json",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "serviceName",
              "value": "DatasetSP.save"
            },
            {
              "name": "outputType",
              "value": "json"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.token }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"serviceName\": \"DatasetSP.save\",\n  \"requestBody\": {\n    \"entityName\": \"AD_TESTE\",\n    \"standAlone\": false,\n    \"fields\": [\"ID\", \"NOME\", \"NUMERO\", \"BASE64\"],\n    \"records\": [\n      {\n        \"values\": {\n          \"1\": \"sasuke\",\n          \"2\": \"23\",\n          \"3\": \"{{ $('Webhook').item.json.body.conteudoBase64 }}\"\n        }\n      }\n    ]\n  }\n}\n",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        128,
        -240
      ],
      "id": "3ab2bf75-0fa3-49ab-89aa-416e5684626b",
      "name": "Roda consulta"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        368,
        -240
      ],
      "id": "43ddae43-30fc-43b0-8b05-9587d10f46ce",
      "name": "Respond to Webhook"
    }
  ],
  "pinData": {},
  "connections": {
    "Validação": {
      "main": [
        [
          {
            "node": "Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Validação",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Token": {
      "main": [
        [
          {
            "node": "Roda consulta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Roda consulta": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respond to Webhook": {
      "main": [
        []
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "6d52b285-bfbe-4db0-a62f-de9a883866ca",
  "meta": {
    "instanceId": "949b8d98ae27b5da298f87134ef7188484791002d472dbe6a2bb2d1ace6650a9"
  },
  "id": "hnQrpCGOeY04cuxk",
  "tags": []
}

3- Se tentar enviar uma arquivo Base64 direto para um campo BLOB vai ser salvo porém não visualizável e não vai aparecer no output apenas no DB, a melhor forma é mandar para um campo CLOB e depois converter para Binário via trigger.
Segue exemplo funcional em uma tabela teste:


CREATE OR REPLACE TRIGGER TRG_AD_TESTE_IMG

BEFORE INSERT OR UPDATE ON AD_TESTE

FOR EACH ROW

DECLARE

    v_blob       BLOB;

    v_clob       CLOB := :NEW.BASE64;

    v_len        NUMBER;

    v_offset     NUMBER := 1;

    v_buffer_raw RAW(32767);

    v_buffer_vc  VARCHAR2(32767);

    v_chunk_size NUMBER := 12000; 

BEGIN

    -- Só executa se a flag for 'S'

    IF :NEW.CONVERTE = 'S' AND v_clob IS NOT NULL THEN

        

        DBMS_LOB.CREATETEMPORARY(v_blob, TRUE);

        v_len := DBMS_LOB.GETLENGTH(v_clob);

        -- Loop para converter o CLOB em pedaços e montar o BLOB

        WHILE v_offset <= v_len LOOP

            v_buffer_vc := DBMS_LOB.SUBSTR(v_clob, v_chunk_size, v_offset);

            

            -- Converte o pedaço de texto para binário

            v_buffer_raw := UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(v_buffer_vc));

            

            -- Escreve no BLOB final

            DBMS_LOB.WRITEAPPEND(v_blob, UTL_RAW.LENGTH(v_buffer_raw), v_buffer_raw);

            

            v_offset := v_offset + v_chunk_size;

        END LOOP;

        -- Atribui o BLOB resultante ao campo de imagem

        :NEW.IMAGEM := v_blob;

        

        -- Limpa a flag e o campo temporário para economizar espaço

        :NEW.CONVERTE := 'N';

        :NEW.BASE64   := NULL;

        

        DBMS_LOB.FREETEMPORARY(v_blob);

    END IF;

EXCEPTION

    WHEN OTHERS THEN

        IF v_blob IS NOT NULL THEN DBMS_LOB.FREETEMPORARY(v_blob); END IF;

        RAISE_APPLICATION_ERROR(-20001, 'Erro ao processar imagem Base64: ' || SQLERRM);

END;
3
2 respostas