Transfert automatisé de fichiers de Google Drive vers FTP avec journalisation JSON et rapports
Ceci est unFile Management, Miscellaneous, Multimodal AIworkflow d'automatisation du domainecontenant 15 nœuds.Utilise principalement des nœuds comme If, Ftp, Code, Webhook, EmailSend. Transfert automatisé de fichiers de Google Drive vers FTP avec journalisation JSON et rapports
- •Point de terminaison HTTP Webhook (généré automatiquement par n8n)
- •Informations d'identification Google Drive API
Nœuds utilisés (15)
{
"id": "LJmjAaP6VnaYVBF9",
"meta": {
"instanceId": "ade915387b18f7a3b9a14fd8fb677fdbace0ade794de7914e8790d907cd285d0",
"templateCredsSetupCompleted": true
},
"name": "Automated Google Drive to FTP File Transfer with JSON Logging and Reporting",
"tags": [],
"nodes": [
{
"id": "52861d1c-200e-46dc-84cc-964db24965df",
"name": "Note adhésive",
"type": "n8n-nodes-base.stickyNote",
"position": [
224,
400
],
"parameters": {
"width": 444,
"height": 180,
"content": "🔗 **WEBHOOK TRIGGER**\n\nManual trigger endpoint:\nPOST to: `/webhook-transfer-status`\n\nUse for on-demand transfers or external integrations."
},
"typeVersion": 1
},
{
"id": "81c1ff80-5b17-46a2-9b48-d25894340817",
"name": "Déclencheur planifié",
"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": "Get Drive Files",
"type": "n8n-nodes-base.googleDrive",
"position": [
496,
32
],
"parameters": {
"operation": "search"
},
"typeVersion": 3
},
{
"id": "112f4226-ff78-4da8-9d97-b729d2ae54cb",
"name": "Filtrer & Validate Files",
"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": "Process One by One",
"type": "n8n-nodes-base.splitInBatches",
"position": [
896,
32
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "7622280e-523d-40ed-84a6-6467c46470e8",
"name": "Download from 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": "Upload to 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": "Update Notes - Success",
"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": "Update Notes - Error",
"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": "Check if More Files",
"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": "Save Notes 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": "Upload Notes to 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": "Send Report E-mail",
"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": "Déclencheur Webhook Trigger",
"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": "Create Final Report",
"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": {
"90b25c0a-0719-4b24-ac62-e61781e27533": {
"main": [
[
{
"node": "9cf1b93b-5584-48d9-bb96-91c2665719cf",
"type": "main",
"index": 0
}
]
]
},
"fb27fb5b-5ff4-4bb4-82e3-44ad39b72022": {
"main": [
[
{
"node": "Filter & Validate Files",
"type": "main",
"index": 0
}
]
]
},
"25732bf1-2c41-44b3-bcbf-a492f30be6e9": {
"main": [
[
{
"node": "b400936c-4f5d-4b7e-b414-38accc14bd7a",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "fb27fb5b-5ff4-4bb4-82e3-44ad39b72022",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "fb27fb5b-5ff4-4bb4-82e3-44ad39b72022",
"type": "main",
"index": 0
}
]
]
},
"d9f3620c-c532-43fa-9b8b-0b6e47737fd0": {
"main": [
[
{
"node": "7622280e-523d-40ed-84a6-6467c46470e8",
"type": "main",
"index": 0
}
],
[
{
"node": "e5ebea62-bc9c-4a56-a52d-0a657df83e2c",
"type": "main",
"index": 0
}
]
]
},
"ea8a7f9c-b7a8-4a15-8584-7fe59a7d18bd": {
"main": [
[
{
"node": "d9f3620c-c532-43fa-9b8b-0b6e47737fd0",
"type": "main",
"index": 0
}
],
[
{
"node": "25732bf1-2c41-44b3-bcbf-a492f30be6e9",
"type": "main",
"index": 0
}
]
]
},
"e5ebea62-bc9c-4a56-a52d-0a657df83e2c": {
"main": [
[
{
"node": "25732bf1-2c41-44b3-bcbf-a492f30be6e9",
"type": "main",
"index": 0
}
]
]
},
"7622280e-523d-40ed-84a6-6467c46470e8": {
"main": [
[
{
"node": "90b25c0a-0719-4b24-ac62-e61781e27533",
"type": "main",
"index": 0
}
]
]
},
"5ea1483c-1b95-443e-b57f-08a192bc76f9": {
"main": [
[
{
"node": "ea8a7f9c-b7a8-4a15-8584-7fe59a7d18bd",
"type": "main",
"index": 0
}
]
]
},
"b400936c-4f5d-4b7e-b414-38accc14bd7a": {
"main": [
[
{
"node": "Send Report Email",
"type": "main",
"index": 0
}
]
]
},
"9cf1b93b-5584-48d9-bb96-91c2665719cf": {
"main": [
[
{
"node": "ea8a7f9c-b7a8-4a15-8584-7fe59a7d18bd",
"type": "main",
"index": 0
}
]
]
},
"Filter & Validate Files": {
"main": [
[
{
"node": "d9f3620c-c532-43fa-9b8b-0b6e47737fd0",
"type": "main",
"index": 0
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Intermédiaire - Gestion de fichiers, Divers, IA Multimodale
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
Dariusz Koryto
@dakoPartager ce workflow