自动化Google Drive到FTP文件传输与JSON日志记录和报告
中级
这是一个File Management, Miscellaneous, Multimodal AI领域的自动化工作流,包含 15 个节点。主要使用 If, Ftp, Code, Webhook, EmailSend 等节点。 自动化Google Drive到FTP文件传输与JSON日志记录和报告
前置要求
- •HTTP Webhook 端点(n8n 会自动生成)
- •Google Drive API 凭证
使用的节点 (15)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "LJmjAaP6VnaYVBF9",
"meta": {
"instanceId": "ade915387b18f7a3b9a14fd8fb677fdbace0ade794de7914e8790d907cd285d0",
"templateCredsSetupCompleted": true
},
"name": "自动化 Google Drive 到 FTP 文件传输与 JSON 日志记录和报告",
"tags": [],
"nodes": [
{
"id": "52861d1c-200e-46dc-84cc-964db24965df",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
224,
400
],
"parameters": {
"width": 444,
"height": 180,
"content": "🔗 **WEBHOOK 触发器**"
},
"typeVersion": 1
},
{
"id": "81c1ff80-5b17-46a2-9b48-d25894340817",
"name": "定时触发器",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
304,
32
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"typeVersion": 1.1
},
{
"id": "fb27fb5b-5ff4-4bb4-82e3-44ad39b72022",
"name": "获取 Drive 文件",
"type": "n8n-nodes-base.googleDrive",
"position": [
496,
32
],
"parameters": {
"operation": "search"
},
"typeVersion": 3
},
{
"id": "112f4226-ff78-4da8-9d97-b729d2ae54cb",
"name": "过滤和验证文件",
"type": "n8n-nodes-base.code",
"position": [
704,
32
],
"parameters": {
"jsCode": "const transferNotes = {\n metadata: {\n created: new Date().toISOString(),\n lastUpdated: new Date().toISOString(),\n totalFiles: 0,\n successfulTransfers: 0,\n failedTransfers: 0,\n skippedFiles: 0\n },\n settings: {\n maxFileSizeMB: 50,\n allowedExtensions: ['.pdf', '.doc', '.docx', '.txt', '.jpg', '.png', '.zip', '.xlsx'],\n autoDeleteAfterTransfer: false,\n verifyTransfer: true\n },\n transfers: [],\n notes: {\n general: 'File transfer from Google Drive to FTP server',\n lastRun: new Date().toISOString(),\n instructions: 'This workflow automatically transfers files from Google Drive to FTP'\n }\n};\n\nconst driveFiles = $input.all();\nconst validFiles = [];\n\nfor (const fileItem of driveFiles) {\n const file = fileItem.json;\n const fileName = file.name;\n const fileSize = parseInt(file.size) || 0;\n const fileExtension = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();\n \n const maxSizeBytes = transferNotes.settings.maxFileSizeMB * 1024 * 1024;\n const isAllowedExtension = transferNotes.settings.allowedExtensions.includes(fileExtension);\n const isSizeOk = fileSize <= maxSizeBytes;\n \n if (isAllowedExtension && isSizeOk) {\n validFiles.push({\n id: file.id,\n name: fileName,\n size: fileSize,\n extension: fileExtension,\n modifiedTime: file.modifiedTime,\n mimeType: file.mimeType,\n transferStatus: 'pending'\n });\n } else {\n transferNotes.transfers.push({\n timestamp: new Date().toISOString(),\n fileId: file.id,\n fileName: fileName,\n fileSize: fileSize,\n status: 'skipped',\n reason: !isAllowedExtension ? 'Invalid file extension' : 'File too large',\n details: {\n extension: fileExtension,\n sizeMB: Math.round(fileSize / 1024 / 1024 * 100) / 100\n }\n });\n transferNotes.metadata.skippedFiles++;\n }\n}\n\ntransferNotes.metadata.totalFiles = validFiles.length;\n\nreturn [{\n json: {\n transferNotes: transferNotes,\n validFiles: validFiles,\n totalFilesFound: driveFiles.length,\n validFilesCount: validFiles.length\n }\n}];"
},
"typeVersion": 2
},
{
"id": "d9f3620c-c532-43fa-9b8b-0b6e47737fd0",
"name": "逐个处理",
"type": "n8n-nodes-base.splitInBatches",
"position": [
896,
32
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "7622280e-523d-40ed-84a6-6467c46470e8",
"name": "从 Drive 下载",
"type": "n8n-nodes-base.googleDrive",
"position": [
1104,
32
],
"parameters": {
"fileId": "={{ $json.validFiles[$json.batchIndex].id }}",
"options": {},
"operation": "download"
},
"typeVersion": 3
},
{
"id": "90b25c0a-0719-4b24-ac62-e61781e27533",
"name": "上传到 FTP",
"type": "n8n-nodes-base.ftp",
"position": [
1296,
32
],
"parameters": {
"path": "/remote/directory/{{ $json.validFiles[$json.batchIndex].name }}",
"options": {}
},
"typeVersion": 1
},
{
"id": "9cf1b93b-5584-48d9-bb96-91c2665719cf",
"name": "更新备注 - 成功",
"type": "n8n-nodes-base.code",
"position": [
1504,
-64
],
"parameters": {
"jsCode": "const currentFile = $('split-files').item.json.validFiles[$('split-files').item.json.batchIndex];\nconst transferNotes = $('filter-files').item.json.transferNotes;\n\nconst transferRecord = {\n timestamp: new Date().toISOString(),\n fileId: currentFile.id,\n fileName: currentFile.name,\n fileSize: currentFile.size,\n status: 'success',\n transferDuration: null,\n ftpPath: `/remote/directory/${currentFile.name}`,\n details: {\n extension: currentFile.extension,\n mimeType: currentFile.mimeType,\n sizeMB: Math.round(currentFile.size / 1024 / 1024 * 100) / 100\n }\n};\n\ntransferNotes.transfers.push(transferRecord);\ntransferNotes.metadata.successfulTransfers++;\ntransferNotes.metadata.lastUpdated = new Date().toISOString();\n\nreturn [{\n json: {\n transferNotes: transferNotes,\n currentTransfer: transferRecord,\n message: `Successfully transferred file: ${currentFile.name}`\n }\n}];"
},
"typeVersion": 2
},
{
"id": "5ea1483c-1b95-443e-b57f-08a192bc76f9",
"name": "更新备注 - 错误",
"type": "n8n-nodes-base.code",
"position": [
1504,
144
],
"parameters": {
"jsCode": "const currentFile = $('split-files').item.json.validFiles[$('split-files').item.json.batchIndex];\nconst transferNotes = $('filter-files').item.json.transferNotes;\nconst errorInfo = $input.last().error || 'Unknown error';\n\nconst transferRecord = {\n timestamp: new Date().toISOString(),\n fileId: currentFile.id,\n fileName: currentFile.name,\n fileSize: currentFile.size,\n status: 'failed',\n errorMessage: errorInfo.message || errorInfo,\n details: {\n extension: currentFile.extension,\n mimeType: currentFile.mimeType,\n sizeMB: Math.round(currentFile.size / 1024 / 1024 * 100) / 100\n }\n};\n\ntransferNotes.transfers.push(transferRecord);\ntransferNotes.metadata.failedTransfers++;\ntransferNotes.metadata.lastUpdated = new Date().toISOString();\n\nreturn [{\n json: {\n transferNotes: transferNotes,\n currentTransfer: transferRecord,\n message: `Error during file transfer: ${currentFile.name} - ${errorInfo.message || errorInfo}`\n }\n}];"
},
"typeVersion": 2
},
{
"id": "ea8a7f9c-b7a8-4a15-8584-7fe59a7d18bd",
"name": "检查是否有更多文件",
"type": "n8n-nodes-base.if",
"position": [
1696,
32
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "success-condition",
"operator": {
"type": "boolean",
"operation": "equal"
},
"leftValue": "={{ $json.batchIndex < ($json.validFiles.length - 1) }}",
"rightValue": true
}
]
}
},
"typeVersion": 2
},
{
"id": "25732bf1-2c41-44b3-bcbf-a492f30be6e9",
"name": "保存备注 JSON",
"type": "n8n-nodes-base.writeBinaryFile",
"position": [
1904,
32
],
"parameters": {
"options": {},
"fileName": "transfer_notes_{{ new Date().toISOString().split('T')[0] }}.json"
},
"typeVersion": 1
},
{
"id": "b400936c-4f5d-4b7e-b414-38accc14bd7a",
"name": "上传备注到 Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
2096,
32
],
"parameters": {
"name": "transfer_notes_{{ new Date().toISOString().split('T')[0] }}.json",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "/ (Root folder)"
}
},
"typeVersion": 3
},
{
"id": "9a4bffa9-6d4b-495e-af69-68884eeadaab",
"name": "发送报告邮件",
"type": "n8n-nodes-base.emailSend",
"position": [
2304,
32
],
"webhookId": "4ef2b12e-aae1-4c93-a034-13bdda075fad",
"parameters": {
"options": {
"appendAttribution": false
},
"subject": "Google Drive to FTP File Transfer - Report"
},
"typeVersion": 2.1
},
{
"id": "234ca9a5-6ce6-470d-b1f4-31671cf782c3",
"name": "Webhook触发器",
"type": "n8n-nodes-base.webhook",
"position": [
304,
240
],
"webhookId": "transfer-webhook-id",
"parameters": {
"path": "/webhook-transfer-status",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2
},
{
"id": "e5ebea62-bc9c-4a56-a52d-0a657df83e2c",
"name": "创建最终报告",
"type": "n8n-nodes-base.code",
"position": [
1904,
240
],
"parameters": {
"jsCode": "const transferNotes = $json.transferNotes;\nconst summary = {\n executionDate: new Date().toLocaleString('en-US'),\n totalFiles: transferNotes.metadata.totalFiles,\n successful: transferNotes.metadata.successfulTransfers,\n failed: transferNotes.metadata.failedTransfers,\n skipped: transferNotes.metadata.skippedFiles,\n successRate: transferNotes.metadata.totalFiles > 0 ? Math.round((transferNotes.metadata.successfulTransfers / transferNotes.metadata.totalFiles) * 100) : 0,\n settings: transferNotes.settings,\n lastUpdated: transferNotes.metadata.lastUpdated\n};\n\nconst successfulTransfers = transferNotes.transfers.filter(t => t.status === 'success').map(t => ({\n fileName: t.fileName,\n sizeMB: t.details.sizeMB,\n timestamp: t.timestamp\n}));\n\nconst failedTransfers = transferNotes.transfers.filter(t => t.status === 'failed').map(t => ({\n fileName: t.fileName,\n error: t.errorMessage,\n timestamp: t.timestamp\n}));\n\nreturn [{\n json: {\n summary: summary,\n successfulTransfers: successfulTransfers,\n failedTransfers: failedTransfers,\n fullNotes: transferNotes\n }\n}];"
},
"typeVersion": 2
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "ce584da0-35fd-4b92-a862-13b3256a376b",
"connections": {
"Upload to FTP": {
"main": [
[
{
"node": "Update Notes - Success",
"type": "main",
"index": 0
}
]
]
},
"Get Drive Files": {
"main": [
[
{
"node": "Filter & Validate Files",
"type": "main",
"index": 0
}
]
]
},
"Save Notes JSON": {
"main": [
[
{
"node": "Upload Notes to Drive",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Get Drive Files",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Get Drive Files",
"type": "main",
"index": 0
}
]
]
},
"Process One by One": {
"main": [
[
{
"node": "Download from Drive",
"type": "main",
"index": 0
}
],
[
{
"node": "Create Final Report",
"type": "main",
"index": 0
}
]
]
},
"Check if More Files": {
"main": [
[
{
"node": "Process One by One",
"type": "main",
"index": 0
}
],
[
{
"node": "Save Notes JSON",
"type": "main",
"index": 0
}
]
]
},
"Create Final Report": {
"main": [
[
{
"node": "Save Notes JSON",
"type": "main",
"index": 0
}
]
]
},
"Download from Drive": {
"main": [
[
{
"node": "Upload to FTP",
"type": "main",
"index": 0
}
]
]
},
"Update Notes - Error": {
"main": [
[
{
"node": "Check if More Files",
"type": "main",
"index": 0
}
]
]
},
"Upload Notes to Drive": {
"main": [
[
{
"node": "Send Report Email",
"type": "main",
"index": 0
}
]
]
},
"Update Notes - Success": {
"main": [
[
{
"node": "Check if More Files",
"type": "main",
"index": 0
}
]
]
},
"Filter & Validate Files": {
"main": [
[
{
"node": "Process One by One",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
中级 - 文件管理, 杂项, 多模态 AI
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
使用Google Drive存储和Telegram提醒自动化Instagram Reel下载
使用Google Drive存储和Telegram提醒自动化Instagram Reel下载
If
Code
Webhook
+6
11 节点Aryan Shinde
文件管理
我的工作流程 2
带智能清理和邮件通知的自动化FTP文件迁移
Ftp
Set
Filter
+3
15 节点Dariusz Koryto
文件管理
自动下载 Reddit 表情包到 Google Drive,含重复检测和 Telegram 提醒
自动下载 Reddit 表情包到 Google Drive,包含重复检测和 Telegram 提醒
If
Set
Code
+10
20 节点Vitorio Magalhães
文件管理
每日 WhatsApp 群组智能分析:GPT-4.1 分析与语音消息转录
每日 WhatsApp 群组智能分析:GPT-4.1 分析与语音消息转录
If
Set
Code
+20
52 节点Daniel Lianes
杂项
使用Gmail和Google Drive存储自动化PDF发票生成与发送
使用Gmail和Google Drive存储自动化PDF发票生成与发送
Code
Webhook
Email Send
+4
13 节点Ibrahim Emre POLAT
杂项
Google广告活动报告自动生成到Google表格(含Airtable客户管理)
Google广告活动报告自动生成到Google表格(含Airtable客户管理)
If
Code
Wait
+6
31 节点Growth AI
杂项