The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Postagem Redes \u2014 Portal: Arquivos",
"description": null,
"isArchived": false,
"nodes": [
{
"parameters": {
"content": "## Arquivos protegidos\n\nEntrega somente m\u00eddia pertencente a um conte\u00fado conhecido.\n\nQuando a URL p\u00fablica estiver habilitada, valida expira\u00e7\u00e3o e assinatura HMAC antes de ler o arquivo.",
"width": 520,
"height": 175,
"color": 5
},
"name": "Resumo operacional",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-360,
-290
]
},
{
"parameters": {
"httpMethod": "GET",
"path": "postagem-redes-arquivo",
"responseMode": "responseNode",
"options": {}
},
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-280,
0
]
},
{
"parameters": {
"jsCode": "\nconst fs = require('fs');\nconst path = require('path');\nconst crypto = require('crypto');\nconst ROOT = '/files/postagem-redes';\nconst INPUT = path.join(ROOT, 'entrada');\nconst STATE = path.join(ROOT, 'state.json');\nconst allowedStatuses = new Set(['pendente','aprovado','agendado','rejeitado','incompleto','publicado','parcial','falhou']);\nfunction slug(value) { const base=String(value).normalize('NFD').replace(/[\\u0300-\\u036f]/g,'').toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/(^-|-$)/g,'').slice(0,70)||'conteudo'; let h=0; for(const c of String(value)) h=((h<<5)-h+c.charCodeAt(0))|0; return base+'-'+(h>>>0).toString(36); }\nfunction safeText(value,max=5000){return String(value??'').replace(/\\0/g,'').trim().slice(0,max)}\nfunction readJson(file,fallback){try{return JSON.parse(fs.readFileSync(file,'utf8'))}catch{return fallback}}\nfunction saveState(state){const lock=STATE+'.lock'; let fd; try{fd=fs.openSync(lock,'wx')}catch{throw new Error('Outra altera\u00e7\u00e3o est\u00e1 em andamento. Atualize a p\u00e1gina e tente novamente.')} try{const temp=STATE+'.tmp';fs.writeFileSync(temp,JSON.stringify(state,null,2),'utf8');fs.renameSync(temp,STATE)}finally{if(fd!==undefined)fs.closeSync(fd);try{fs.unlinkSync(lock)}catch{}}}\nfunction scan(){\n fs.mkdirSync(INPUT,{recursive:true});\n const state=readJson(STATE,{version:1,records:{}}); state.records??={};\n const folders=fs.readdirSync(INPUT,{withFileTypes:true}).filter(x=>x.isDirectory()).map(x=>x.name);\n const items=[];\n for(const folder of folders){\n const dir=path.join(INPUT,folder);\n const files=fs.readdirSync(dir,{withFileTypes:true}).filter(x=>x.isFile()).map(x=>x.name);\n const slides=files.filter(x=>/\\.(png|jpe?g|webp)$/i.test(x)).sort((a,b)=>a.localeCompare(b,'pt-BR',{numeric:true}));\n const assetVersion=Math.max(0,...slides.map(file=>Math.floor(fs.statSync(path.join(dir,file)).mtimeMs)));\n const captionFile=files.find(x=>x.toLowerCase()==='texto.txt');\n const originalCaption=captionFile?safeText(fs.readFileSync(path.join(dir,captionFile),'utf8')):'';\n const id=slug(folder); const old=state.records[id]||{};\n const status=slides.length<1||!originalCaption&&!old.caption?'incompleto':allowedStatuses.has(old.status)?old.status:'pendente';\n items.push({id,folder,title:old.title||folder,slides,assetVersion,caption:old.caption??originalCaption,brief:old.brief||'',status,networks:Array.isArray(old.networks)?old.networks:[],scheduleAt:old.scheduleAt||'',updatedAt:old.updatedAt||'',aiDraft:old.aiDraft&&typeof old.aiDraft==='object'?old.aiDraft:null,deliveries:old.deliveries&&typeof old.deliveries==='object'?old.deliveries:{},audit:Array.isArray(old.audit)?old.audit:[]});\n }\n return {state,items};\n}\n\nconst query=$input.first().json.query||{}; const id=safeText(query.id,130); const file=safeText(query.file,200); if(!id||!file||path.basename(file)!==file||!/^.+\\.(png|jpe?g|webp)$/i.test(file)) throw new Error('Arquivo inv\u00e1lido.'); const requireSignature=String($env.SOCIAL_MEDIA_REQUIRE_SIGNED_URLS||'').toLowerCase()==='true'; if(requireSignature){const exp=Number(query.exp); const supplied=String(query.sig||''); const secret=String($env.SOCIAL_MEDIA_SIGNING_SECRET||''); if(!secret||!Number.isFinite(exp)||exp<Math.floor(Date.now()/1000)||exp>Math.floor(Date.now()/1000)+21600||!supplied) throw new Error('Link de m\u00eddia ausente, expirado ou inv\u00e1lido.'); const expected=crypto.createHmac('sha256',secret).update(id+':'+file+':'+exp).digest('base64url'); const valid=supplied.length===expected.length&&crypto.timingSafeEqual(Buffer.from(supplied),Buffer.from(expected)); if(!valid) throw new Error('Assinatura de m\u00eddia inv\u00e1lida.')} const {items}=scan(); const content=items.find(x=>x.id===id); if(!content||!content.slides.includes(file)) throw new Error('Imagem n\u00e3o encontrada.'); const full=path.join(INPUT,content.folder,file); const data=fs.readFileSync(full); const mime=/\\.png$/i.test(file)?'image/png':/\\.webp$/i.test(file)?'image/webp':'image/jpeg'; return [{json:{},binary:{data:{data:data.toString('base64'),mimeType:mime,fileName:file}}}];"
},
"name": "Processar",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
0,
0
]
},
{
"parameters": {
"respondWith": "binary",
"responseBinaryPropertyName": "data",
"options": {
"responseHeaders": {
"entries": [
{
"name": "Cache-Control",
"value": "private, max-age=604800, immutable"
}
]
}
}
},
"name": "Responder",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
280,
0
]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Processar",
"type": "main",
"index": 0
}
]
]
},
"Processar": {
"main": [
[
{
"node": "Responder",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"availableInMCP": false
},
"nodeGroups": [],
"activeVersionId": "a6214fa8-c892-4a94-a29c-7f020df86b3c",
"versionCounter": 6,
"triggerCount": 1,
"sourceWorkflowId": null,
"versionMetadata": {
"name": "Postagem Redes \u2014 Portal: Arquivos",
"description": null
},
"active": false
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Postagem Redes — Portal: Arquivos. Webhook trigger; 4 nodes.
Source: https://github.com/Mayconxzdev/PostagemRedes/blob/main/workflows/06-portal-arquivos.sanitized.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
A production-ready authentication workflow implementing secure user registration, login, token verification, and refresh token mechanisms. Perfect for adding authentication to any application without
Portfolio Orchestrator. Uses httpRequest. Webhook trigger; 59 nodes.
This n8n template demonstrates how a simple Multi-Layer Perceptron (MLP) neural network can predict housing prices. The prediction is based on four key features, processed through a three-layer model.
github code Try yourself
This workflow receives new consult bookings via webhook (Calendly v2 or a generic scheduling tool), generates timed confirmation and reminder messages, runs each SMS through a separate compliance work