I have a workflow which summarizes CNN News into an HTML table.
The table is created but I cannot figure out how to upload it to Google Drive.
I get an error saying “This operation expects the node’s input to contain a binary file 'htmlFile” but none was found."
How do I create a binary file?
{
"name": "CNN RSS Summary",
"nodes": [
{
"parameters": {
"url": "http://rss.cnn.com/rss/edition.rss",
"options": {}
},
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"position": [
304,
208
],
"id": "generated-97b20896-1ff1-4768-a996-0b5e3cfedd7f"
},
{
"parameters": {
"options": {
"attrkey": "$",
"charkey": "_",
"explicitArray": false,
"explicitRoot": true,
"ignoreAttrs": false,
"mergeAttrs": true,
"normalize": false,
"normalizeTags": false,
"trim": false
}
},
"name": "Parse XML",
"type": "n8n-nodes-base.xml",
"position": [
528,
208
],
"id": "generated-49bde392-11de-4b76-a647-26e5ad4f1c05"
},
{
"parameters": {
"functionCode": "// Get the array of articles from the parsed RSS feed\nconst items = $json.rss.channel.item;\n\n// If only one article, wrap in array\nconst articles = Array.isArray(items) ? items : [items];\n\n// Take the first 10 articles\nreturn articles.slice(0, 10).map(article => ({ json: article }));"
},
"name": "Extract Top 10 Articles",
"type": "n8n-nodes-base.function",
"position": [
752,
208
],
"id": "generated-a34dfdad-911d-4a34-80d6-5694cacd8b3c"
},
{
"parameters": {
"fromEmail": "[email protected]",
"toEmail": "[email protected]",
"subject": "CNN RSS News Summary",
"emailFormat": "text",
"options": {
"appendAttribution": true,
"attachments": "=\n",
"ccEmail": "",
"bccEmail": "",
"allowUnauthorizedCerts": false,
"replyTo": ""
}
},
"name": "Send Email (SMTP)",
"type": "n8n-nodes-base.emailSend",
"position": [
1888,
208
],
"id": "generated-b04c4190-e04e-46d4-bb81-6b5ef64157bd",
"webhookId": "042acfc7-50d0-4317-ab4d-382eff21977f",
"credentials": {
"smtp": {
"id": "X5rhsRBwTsi3OyqS",
"name": "SMTP account"
}
}
},
{
"parameters": {
"content": "## CNN RSS Email Summary Workflow\n\n1. **HTTP Request**: Fetches CNN RSS feed.\n2. **Parse XML**: Converts XML to JSON.\n3. **Extract Top 10 Articles**: Selects the 10 most recent articles.\n4. **Summarize with OpenAI**: Summarizes each article (bullets, pros, cons).\n5. **Build HTML Table**: Formats results as a styled HTML table.\n6. **Send Email (SMTP)**: Emails the HTML table to [email protected].\n\n⚡ You can schedule this workflow with a trigger node for automation!",
"height": 340,
"width": 600,
"color": 5
},
"name": "Workflow Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
848,
48
],
"id": "generated-7b9da9b7-4456-4f0b-8c67-cd4f261fd885"
},
{
"parameters": {},
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"position": [
80,
208
],
"id": "generated-9d16467f-e989-4101-b3d5-e7b07c8ed620"
},
{
"parameters": {
"options": {
"summarizationMethodAndPrompts": {
"values": {
"combineMapPrompt": "Write a concise summary of the following article. Provide:\n- 3-5 bullet points summarizing the main content\n- 2-3 pros\n- 2-3 cons\n\n\"{text}\"\n\nCONCISE SUMMARY BULLETS:\nPROS:\nCONS:",
"prompt": "Write a concise summary of the following article. Provide:\n- 3-5 bullet points summarizing the main content\n- 2-3 pros\n- 2-3 cons\n\n\"{text}\"\n\nCONCISE SUMMARY BULLETS:\nPROS:\nCONS:"
}
}
}
},
"type": "@n8n/n8n-nodes-langchain.chainSummarization",
"typeVersion": 2.1,
"position": [
960,
208
],
"id": "9098e69d-d214-456b-aed0-ff42d54f2a5e",
"name": "Summarization Chain",
"alwaysOutputData": true
},
{
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.2,
"position": [
896,
416
],
"id": "53f283ec-4956-40d6-bd5b-df3ce8d8f2bc",
"name": "OpenAI Chat Model",
"credentials": {
"openAiApi": {
"id": "xjEGLjNNtlk2c7OM",
"name": "OpenAi account"
}
}
},
{
"parameters": {
"jsCode": "// Create HTML file for Google Drive upload\nlet html = `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <title>CNN RSS News Summary - ${new Date().toLocaleDateString()}</title>\n <style>\n body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }\n .container { max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; }\n h1 { color: #003366; text-align: center; }\n table { border-collapse: collapse; width: 100%; }\n th, td { border: 1px solid #ddd; padding: 12px; vertical-align: top; }\n th { background: #003366; color: #fff; }\n tr:nth-child(even) { background: #f9f9f9; }\n ul { margin: 0; padding-left: 20px; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <h1>CNN RSS News Summary</h1>\n <p style=\"text-align: center; color: #666;\">Generated on: ${new Date().toLocaleDateString()}</p>\n <table>\n <tr><th>Article #</th><th>Summary</th><th>Pros</th><th>Cons</th></tr>`;\n\nfor (let i = 0; i < items.length; i++) {\n const item = items[i];\n const fullSummaryText = item?.json?.output?.text || '';\n const title = `${i + 1}`;\n \n let summaryBullets = 'No summary available';\n let pros = 'No pros identified';\n let cons = 'No cons identified';\n\n if (fullSummaryText) {\n const sections = fullSummaryText.split(/\\n\\n/);\n \n for (const section of sections) {\n const lines = section.trim().split('\\n');\n \n if (lines[0].includes('SUMMARY BULLETS')) {\n const bulletLines = lines.slice(1).filter(line => line.trim().startsWith('-'));\n if (bulletLines.length > 0) {\n summaryBullets = '<ul>' + bulletLines.map(line => \n `<li>${line.trim().substring(1).trim()}</li>`\n ).join('') + '</ul>';\n }\n } else if (lines[0].includes('PROS')) {\n const prosLinesList = lines.slice(1).filter(line => line.trim().startsWith('-'));\n if (prosLinesList.length > 0) {\n pros = '<ul>' + prosLinesList.map(line => \n `<li>${line.trim().substring(1).trim()}</li>`\n ).join('') + '</ul>';\n }\n } else if (lines[0].includes('CONS')) {\n const consLinesList = lines.slice(1).filter(line => line.trim().startsWith('-'));\n if (consLinesList.length > 0) {\n cons = '<ul>' + consLinesList.map(line => \n `<li>${line.trim().substring(1).trim()}</li>`\n ).join('') + '</ul>';\n }\n }\n }\n }\n\n html += `<tr><td style=\"text-align: center; font-weight: bold;\">${title}</td><td>${summaryBullets}</td><td>${pros}</td><td>${cons}</td></tr>`;\n}\n\nhtml += `</table></div></body></html>`;\n\nconst filename = `CNN_Summary_${new Date().toISOString().split('T')[0]}.html`;\n\nreturn [{\n json: {\n htmlFile: html,\n filename: filename,\n emailBody: `Your CNN RSS News Summary is ready!\\n\\nThe HTML report has been saved to Google Drive as: ${filename}\\n\\nTo view: Go to https://drive.google.com and open the file.\\n\\nThis summary contains ${items.length} articles with full analysis.\\n\\nBest regards,\\nNews Bot`\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1344,
208
],
"id": "e73451c3-9c07-4d1f-86d3-d1d951744ba5",
"name": "Build HTML Table"
},
{
"parameters": {
"operation": "createFromText",
"content": "htmlFile",
"name": "CNN_Summary.html",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "/ (Root folder)"
},
"options": {}
},
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
1712,
208
],
"id": "ae1b022d-60dd-48ae-82b8-f1cdb42edbb6",
"name": "Create file from text",
"credentials": {
"googleDriveOAuth2Api": {
"id": "vl5QRzFIsYJctiJr",
"name": "Google Drive account"
}
}
},
{
"parameters": {
"inputDataFieldName": "htmlFile",
"name": "CNN_News_Summary_File.html",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "/ (Root folder)"
},
"options": {}
},
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
1552,
208
],
"id": "874554bc-ec2b-4d60-b8dd-a552c2706bd6",
"name": "Upload file",
"credentials": {
"googleDriveOAuth2Api": {
"id": "vl5QRzFIsYJctiJr",
"name": "Google Drive account"
}
}
}
],
"pinData": {},
"connections": {
"HTTP Request": {
"main": [
[
{
"node": "Parse XML",
"type": "main",
"index": 0
}
]
]
},
"Parse XML": {
"main": [
[
{
"node": "Extract Top 10 Articles",
"type": "main",
"index": 0
}
]
]
},
"Extract Top 10 Articles": {
"main": [
[
{
"node": "Summarization Chain",
"type": "main",
"index": 0
}
]
]
},
"Manual Trigger": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"Summarization Chain": {
"main": [
[
{
"node": "Build HTML Table",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Summarization Chain",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Build HTML Table": {
"main": [
[
{
"node": "Upload file",
"type": "main",
"index": 0
}
]
]
},
"Create file from text": {
"main": [
[
{
"node": "Send Email (SMTP)",
"type": "main",
"index": 0
}
]
]
},
"Upload file": {
"main": [
[
{
"node": "Create file from text",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "c992cba0-a9d8-40e5-9d59-63d30117eeeb",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "ddc8b19b7fa20047424f31044d87873eaee7496fb5be5378767f1db53a15213a"
},
"id": "b9JWzibNlwNVIvqW",
"tags": []
}```



