This workflow follows the Execute Workflow Trigger → HTTP Request recipe pattern — see all workflows that pair these two integrations.
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": "Image Processing - DocuSearch",
"nodes": [
{
"parameters": {},
"id": "workflow-trigger",
"name": "\u30ef\u30fc\u30af\u30d5\u30ed\u30fc\u958b\u59cb",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1,
"position": [
0,
0
]
},
{
"parameters": {
"filePath": "={{ $json.path }}",
"options": {}
},
"id": "read-image-file",
"name": "\u753b\u50cf\u30d5\u30a1\u30a4\u30eb\u8aad\u8fbc",
"type": "n8n-nodes-base.readBinaryFile",
"typeVersion": 1,
"position": [
220,
0
]
},
{
"parameters": {
"jsCode": "// EXIF\u60c5\u5831\u3092\u62bd\u51fa\u3059\u308b\u30b3\u30fc\u30c9\uff08JPEG/TIFF\u5bfe\u5fdc\uff09\nconst item = $input.first();\nconst binaryData = item.binary?.data;\nconst prevJson = $('\u30ef\u30fc\u30af\u30d5\u30ed\u30fc\u958b\u59cb').first().json;\n\nif (!binaryData) {\n return [{\n json: {\n ...prevJson,\n exif: { error: 'No binary data found', has_gps: false }\n }\n }];\n}\n\n// Base64\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\nconst binaryBuffer = await this.helpers.getBinaryDataBuffer(0, 'data');\nconst base64String = binaryBuffer.toString('base64');\nconst fileName = binaryData.fileName || prevJson.name || 'unknown.jpg';\n\n// EXIF\u89e3\u6790\u95a2\u6570\nfunction parseExif(buffer) {\n const result = {\n datetime: null,\n latitude: null,\n longitude: null,\n has_gps: false,\n camera_make: null,\n camera_model: null\n };\n\n try {\n // JPEG\u30de\u30fc\u30ab\u30fc\u3092\u78ba\u8a8d\n if (buffer[0] !== 0xFF || buffer[1] !== 0xD8) {\n return result; // JPEG\u3067\u306f\u306a\u3044\n }\n\n let offset = 2;\n while (offset < buffer.length - 1) {\n if (buffer[offset] !== 0xFF) {\n offset++;\n continue;\n }\n\n const marker = buffer[offset + 1];\n \n // APP1\u30de\u30fc\u30ab\u30fc\uff08EXIF\uff09\n if (marker === 0xE1) {\n const length = (buffer[offset + 2] << 8) | buffer[offset + 3];\n const exifData = buffer.slice(offset + 4, offset + 2 + length);\n \n // 'Exif\\0\\0'\u3092\u78ba\u8a8d\n if (exifData[0] === 0x45 && exifData[1] === 0x78 && \n exifData[2] === 0x69 && exifData[3] === 0x66) {\n parseExifData(exifData.slice(6), result);\n }\n break;\n }\n \n // SOS\u30de\u30fc\u30ab\u30fc\uff08\u753b\u50cf\u30c7\u30fc\u30bf\u958b\u59cb\uff09\u306b\u9054\u3057\u305f\u3089\u7d42\u4e86\n if (marker === 0xDA) break;\n \n const segmentLength = (buffer[offset + 2] << 8) | buffer[offset + 3];\n offset += 2 + segmentLength;\n }\n } catch (e) {\n result.error = e.message;\n }\n\n return result;\n}\n\nfunction parseExifData(data, result) {\n // \u30a8\u30f3\u30c7\u30a3\u30a2\u30f3\u5224\u5b9a\n const littleEndian = data[0] === 0x49; // 'II'\n \n function readUint16(pos) {\n return littleEndian \n ? data[pos] | (data[pos + 1] << 8)\n : (data[pos] << 8) | data[pos + 1];\n }\n \n function readUint32(pos) {\n return littleEndian\n ? data[pos] | (data[pos + 1] << 8) | (data[pos + 2] << 16) | (data[pos + 3] << 24)\n : (data[pos] << 24) | (data[pos + 1] << 16) | (data[pos + 2] << 8) | data[pos + 3];\n }\n \n function readRational(pos) {\n const num = readUint32(pos);\n const den = readUint32(pos + 4);\n return den !== 0 ? num / den : 0;\n }\n \n function readString(pos, len) {\n let str = '';\n for (let i = 0; i < len && data[pos + i] !== 0; i++) {\n str += String.fromCharCode(data[pos + i]);\n }\n return str.trim();\n }\n \n function convertGPS(degrees, minutes, seconds, ref) {\n let decimal = degrees + minutes / 60 + seconds / 3600;\n if (ref === 'S' || ref === 'W') decimal = -decimal;\n return decimal;\n }\n\n // IFD0\u3092\u89e3\u6790\n const ifd0Offset = readUint32(4);\n let gpsIfdOffset = null;\n let exifIfdOffset = null;\n \n function parseIFD(ifdOffset, isGPS = false) {\n const numEntries = readUint16(ifdOffset);\n let gpsLatRef = 'N', gpsLonRef = 'E';\n let gpsLat = null, gpsLon = null;\n \n for (let i = 0; i < numEntries; i++) {\n const entryOffset = ifdOffset + 2 + i * 12;\n const tag = readUint16(entryOffset);\n const type = readUint16(entryOffset + 2);\n const count = readUint32(entryOffset + 4);\n let valueOffset = entryOffset + 8;\n \n // \u5024\u304c4\u30d0\u30a4\u30c8\u3092\u8d85\u3048\u308b\u5834\u5408\u306f\u30aa\u30d5\u30bb\u30c3\u30c8\u3092\u8aad\u3080\n const typeSize = [0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8][type] || 1;\n if (count * typeSize > 4) {\n valueOffset = readUint32(entryOffset + 8);\n }\n \n if (isGPS) {\n // GPS IFD\n if (tag === 0x01) gpsLatRef = readString(valueOffset, 1); // GPSLatitudeRef\n if (tag === 0x03) gpsLonRef = readString(valueOffset, 1); // GPSLongitudeRef\n if (tag === 0x02) { // GPSLatitude\n gpsLat = [readRational(valueOffset), readRational(valueOffset + 8), readRational(valueOffset + 16)];\n }\n if (tag === 0x04) { // GPSLongitude\n gpsLon = [readRational(valueOffset), readRational(valueOffset + 8), readRational(valueOffset + 16)];\n }\n } else {\n // IFD0 / ExifIFD\n if (tag === 0x010F) result.camera_make = readString(valueOffset, count); // Make\n if (tag === 0x0110) result.camera_model = readString(valueOffset, count); // Model\n if (tag === 0x0132) result.datetime = readString(valueOffset, count); // DateTime\n if (tag === 0x9003) result.datetime = readString(valueOffset, count); // DateTimeOriginal (\u512a\u5148)\n if (tag === 0x8825) gpsIfdOffset = readUint32(valueOffset); // GPSInfoIFDPointer\n if (tag === 0x8769) exifIfdOffset = readUint32(valueOffset); // ExifIFDPointer\n }\n }\n \n if (isGPS && gpsLat && gpsLon) {\n result.latitude = convertGPS(gpsLat[0], gpsLat[1], gpsLat[2], gpsLatRef);\n result.longitude = convertGPS(gpsLon[0], gpsLon[1], gpsLon[2], gpsLonRef);\n result.has_gps = true;\n }\n }\n \n parseIFD(ifd0Offset);\n if (exifIfdOffset) parseIFD(exifIfdOffset);\n if (gpsIfdOffset) parseIFD(gpsIfdOffset, true);\n}\n\n// EXIF\u89e3\u6790\u5b9f\u884c\nconst exifResult = parseExif(binaryBuffer);\n\nconst result = {\n json: {\n originalPath: prevJson.path,\n fileName: fileName,\n base64Data: base64String,\n mimeType: binaryData.mimeType || 'image/jpeg',\n fileSize: binaryData.fileSize,\n exif: exifResult\n }\n};\n\nreturn [result];"
},
"id": "extract-exif",
"name": "EXIF\u62bd\u51fa",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
440,
0
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "has-gps",
"leftValue": "={{ $json.exif.has_gps }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
}
},
"id": "check-gps",
"name": "GPS\u6709\u7121\u30c1\u30a7\u30c3\u30af",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
660,
0
]
},
{
"parameters": {
"method": "GET",
"url": "=https://nominatim.openstreetmap.org/reverse",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "lat",
"value": "={{ $json.exif.latitude }}"
},
{
"name": "lon",
"value": "={{ $json.exif.longitude }}"
},
{
"name": "format",
"value": "json"
},
{
"name": "accept-language",
"value": "ja"
},
{
"name": "addressdetails",
"value": "1"
}
]
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "User-Agent",
"value": "DocuSearch_AI/1.0"
}
]
},
"options": {
"timeout": 10000
}
},
"id": "geocoding",
"name": "\u30b8\u30aa\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
880,
-100
],
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 2000
},
{
"parameters": {
"jsCode": "const item = $input.first();\nconst geoData = item.json;\nconst prevData = $('EXIF\u62bd\u51fa').first().json;\n\n// \u4f4f\u6240\u3092\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\nconst address = geoData.address || {};\nconst parts = [];\n\nif (address.country) parts.push(address.country);\nif (address.state || address.province) parts.push(address.state || address.province);\nif (address.city || address.town || address.village) {\n parts.push(address.city || address.town || address.village);\n}\nif (address.suburb || address.neighbourhood) {\n parts.push(address.suburb || address.neighbourhood);\n}\n\nconst formattedAddress = parts.join(', ') || geoData.display_name || '\u4f4f\u6240\u4e0d\u660e';\n\nreturn [{\n json: {\n ...prevData,\n location: {\n formatted: formattedAddress,\n full: geoData.display_name,\n raw: address\n }\n }\n}];"
},
"id": "format-address",
"name": "\u4f4f\u6240\u30d5\u30a9\u30fc\u30de\u30c3\u30c8",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1100,
-100
]
},
{
"parameters": {
"jsCode": "const item = $input.first();\n\nreturn [{\n json: {\n ...item.json,\n location: {\n formatted: '\u4f4d\u7f6e\u60c5\u5831\u306a\u3057',\n full: null,\n raw: null\n }\n }\n}];"
},
"id": "no-gps",
"name": "\u4f4d\u7f6e\u60c5\u5831\u306a\u3057",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
880,
100
]
},
{
"parameters": {
"jsCode": "// \u753b\u50cf\u306eBase64\u30c7\u30fc\u30bf\u304b\u3089Gemini API\u30ea\u30af\u30a8\u30b9\u30c8\u30da\u30a4\u30ed\u30fc\u30c9\u3092\u69cb\u7bc9\n// \u524d\u306e\u30ce\u30fc\u30c9\u304b\u3089\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\uff08\u4f4f\u6240\u30d5\u30a9\u30fc\u30de\u30c3\u30c8 or \u4f4d\u7f6e\u60c5\u5831\u306a\u3057\uff09\nlet prevData;\ntry {\n prevData = $('\u4f4f\u6240\u30d5\u30a9\u30fc\u30de\u30c3\u30c8').first().json;\n} catch (e) {\n try {\n prevData = $('\u4f4d\u7f6e\u60c5\u5831\u306a\u3057').first().json;\n } catch (e2) {\n prevData = $('EXIF\u62bd\u51fa').first().json;\n }\n}\n\nconst base64Data = prevData.base64Data;\nconst mimeType = prevData.mimeType || 'image/jpeg';\n\nif (!base64Data) {\n throw new Error('No base64Data found for image');\n}\n\n// Gemini API\u30ea\u30af\u30a8\u30b9\u30c8\u30da\u30a4\u30ed\u30fc\u30c9\u3092\u69cb\u7bc9\nconst requestPayload = {\n contents: [{\n parts: [\n {\n text: `\u3053\u306e\u753b\u50cf\u3092\u8a73\u7d30\u306b\u5206\u6790\u3057\u3001\u691c\u7d22\u7528\u306e\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u4f5c\u6210\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u4ee5\u4e0b\u306e\u70b9\u3092\u542b\u3081\u3066\u8a18\u8ff0\u3057\u3066\u304f\u3060\u3055\u3044\uff1a\n\n1. \u5199\u3063\u3066\u3044\u308b\u7269\u4f53\uff08\u5177\u4f53\u7684\u306b\uff09\n - \u5efa\u7269\u304c\u3042\u308b\u5834\u5408\u3001\u305d\u306e\u7a2e\u985e\uff08\u30de\u30f3\u30b7\u30e7\u30f3\u3001\u30d3\u30eb\u3001\u6238\u5efa\u3066\u3001\u30aa\u30d5\u30a3\u30b9\u3001\u5546\u696d\u65bd\u8a2d\u306a\u3069\uff09\n - \u8eca\u4e21\u304c\u3042\u308b\u5834\u5408\u3001\u7a2e\u985e\uff08\u4e57\u7528\u8eca\u3001\u30c8\u30e9\u30c3\u30af\u3001\u30d0\u30a4\u30af\u306a\u3069\uff09\n - \u4eba\u7269\u304c\u3044\u308b\u5834\u5408\u3001\u4eba\u6570\u3068\u72b6\u6cc1\uff08\u30d3\u30b8\u30cd\u30b9\u3001\u30ab\u30b8\u30e5\u30a2\u30eb\u3001\u30a4\u30d9\u30f3\u30c8\u306a\u3069\uff09\n\n2. \u30b7\u30c1\u30e5\u30a8\u30fc\u30b7\u30e7\u30f3\u30fb\u5834\u9762\n - \u98df\u4e8b\u3001\u4f1a\u8b70\u3001\u5de5\u4e8b\u73fe\u5834\u3001\u65c5\u884c\u3001\u30a4\u30d9\u30f3\u30c8\u3001\u65e5\u5e38\u306a\u3069\n - \u6599\u7406\u304c\u3042\u308b\u5834\u5408\u3001\u30b8\u30e3\u30f3\u30eb\uff08\u30a4\u30bf\u30ea\u30a2\u30f3\u3001\u548c\u98df\u3001\u4e2d\u83ef\u3001\u30ab\u30d5\u30a7\u306a\u3069\uff09\n\n3. \u96f0\u56f2\u6c17\u3084\u8272\u5473\n - \u660e\u308b\u3044\u3001\u6697\u3044\u3001\u30e2\u30c0\u30f3\u3001\u30ec\u30c8\u30ed\u3001\u30dd\u30c3\u30d7\u3001\u843d\u3061\u7740\u3044\u305f\u96f0\u56f2\u6c17\u306a\u3069\n\n4. \u8aad\u307f\u53d6\u308c\u308b\u6587\u5b57\u60c5\u5831\n - \u770b\u677f\u3001\u66f8\u7c4d\u3001\u63b2\u793a\u677f\u306a\u3069\u8aad\u3081\u308b\u6587\u5b57\u304c\u3042\u308c\u3070\u8a18\u8ff0\n\n5. \u5834\u6240\u306e\u63a8\u6e2c\n - \u5c4b\u5185/\u5c4b\u5916\u3001\u90fd\u5e02/\u90ca\u5916/\u81ea\u7136\u306a\u3069\n\n\u51fa\u529b\u306f\u65e5\u672c\u8a9e\u306e\u81ea\u7136\u306a\u6587\u7ae0\u3067\u3001\u691c\u7d22\u30ad\u30fc\u30ef\u30fc\u30c9\u5316\u3057\u3084\u3059\u3044\u5f62\u5f0f\u3067\u304a\u9858\u3044\u3057\u307e\u3059\u3002`\n },\n {\n inline_data: {\n mime_type: mimeType,\n data: base64Data\n }\n }\n ]\n }],\n generationConfig: {\n temperature: 0.7,\n maxOutputTokens: 1024\n }\n};\n\nreturn [{\n json: {\n ...prevData,\n geminiPayload: requestPayload\n }\n}];"
},
"id": "prepare-gemini-image",
"name": "Gemini\u30ea\u30af\u30a8\u30b9\u30c8\u6e96\u5099",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1320,
0
]
},
{
"parameters": {
"method": "POST",
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "key",
"value": "={{ $env.GEMINI_API_KEY }}"
}
]
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify($json.geminiPayload) }}",
"options": {
"timeout": 60000
}
},
"id": "gemini-vision",
"name": "Gemini Vision API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
1540,
0
],
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 5000
},
{
"parameters": {
"jsCode": "const item = $input.first();\nconst geminiResponse = item.json;\n\n// \u524d\u306e\u30ce\u30fc\u30c9\u304b\u3089\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\uff08\u4f4f\u6240\u30d5\u30a9\u30fc\u30de\u30c3\u30c8 or \u4f4d\u7f6e\u60c5\u5831\u306a\u3057\uff09\nlet prevData;\ntry {\n prevData = $('\u4f4f\u6240\u30d5\u30a9\u30fc\u30de\u30c3\u30c8').first().json;\n} catch (e) {\n try {\n prevData = $('\u4f4d\u7f6e\u60c5\u5831\u306a\u3057').first().json;\n } catch (e2) {\n prevData = $('EXIF\u62bd\u51fa').first().json;\n }\n}\n\n// Gemini\u30ec\u30b9\u30dd\u30f3\u30b9\u304b\u3089\u30ad\u30e3\u30d7\u30b7\u30e7\u30f3\u3092\u62bd\u51fa\nlet caption = '';\ntry {\n caption = geminiResponse.candidates[0].content.parts[0].text || '';\n} catch (e) {\n caption = '\u30ad\u30e3\u30d7\u30b7\u30e7\u30f3\u751f\u6210\u30a8\u30e9\u30fc';\n}\n\n// Dify\u7528\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u30c6\u30ad\u30b9\u30c8\u3092\u69cb\u7bc9\nconst parts = [];\nparts.push(`\u25a0\u30d5\u30a1\u30a4\u30eb\u540d: ${prevData.fileName}`);\n\nif (prevData.exif && prevData.exif.datetime) {\n parts.push(`\u25a0\u64ae\u5f71\u65e5\u6642: ${prevData.exif.datetime}`);\n}\n\nif (prevData.location && prevData.location.formatted) {\n parts.push(`\u25a0\u64ae\u5f71\u5834\u6240: ${prevData.location.formatted}`);\n}\n\nif (prevData.exif && prevData.exif.latitude && prevData.exif.longitude) {\n parts.push(`\u25a0\u5ea7\u6a19: \u7def\u5ea6${prevData.exif.latitude}, \u7d4c\u5ea6${prevData.exif.longitude}`);\n}\n\nif (prevData.exif && prevData.exif.camera_model) {\n const camera = prevData.exif.camera_make \n ? `${prevData.exif.camera_make} ${prevData.exif.camera_model}`\n : prevData.exif.camera_model;\n parts.push(`\u25a0\u30ab\u30e1\u30e9: ${camera}`);\n}\n\nparts.push('\u25a0\u753b\u50cf\u5185\u5bb9\u306e\u8aac\u660e:');\nparts.push(caption);\n\nconst documentText = parts.join('\\n');\n\nreturn [{\n json: {\n ...prevData,\n visionCaption: caption,\n documentText: documentText\n }\n}];"
},
"id": "build-document",
"name": "\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u69cb\u7bc9",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1760,
0
]
},
{
"parameters": {
"method": "POST",
"url": "http://dify-api:5001/v1/datasets/b6e67602-dbd0-4777-bf44-de9ab18a8a11/document/create-by-text",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"name\": \"{{ $json.originalPath.replace('/watch/', '') }}\",\n \"text\": {{ JSON.stringify($json.documentText) }},\n \"indexing_technique\": \"high_quality\",\n \"process_rule\": {\n \"mode\": \"automatic\"\n }\n}",
"options": {
"timeout": 30000
}
},
"id": "dify-index",
"name": "Dify\u767b\u9332",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
1980,
0
],
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 3000,
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const item = $input.first();\nconst prevData = $('\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u69cb\u7bc9').first().json;\nconst difyResponse = item.json;\n\nreturn [{\n json: {\n success: true,\n fileName: prevData.fileName,\n originalPath: prevData.originalPath,\n documentId: difyResponse.document?.id || null,\n processedAt: new Date().toISOString()\n }\n}];"
},
"id": "result",
"name": "\u7d50\u679c\u51fa\u529b",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2200,
0
]
}
],
"connections": {
"\u30ef\u30fc\u30af\u30d5\u30ed\u30fc\u958b\u59cb": {
"main": [
[
{
"node": "\u753b\u50cf\u30d5\u30a1\u30a4\u30eb\u8aad\u8fbc",
"type": "main",
"index": 0
}
]
]
},
"\u753b\u50cf\u30d5\u30a1\u30a4\u30eb\u8aad\u8fbc": {
"main": [
[
{
"node": "EXIF\u62bd\u51fa",
"type": "main",
"index": 0
}
]
]
},
"EXIF\u62bd\u51fa": {
"main": [
[
{
"node": "GPS\u6709\u7121\u30c1\u30a7\u30c3\u30af",
"type": "main",
"index": 0
}
]
]
},
"GPS\u6709\u7121\u30c1\u30a7\u30c3\u30af": {
"main": [
[
{
"node": "\u30b8\u30aa\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0",
"type": "main",
"index": 0
}
],
[
{
"node": "\u4f4d\u7f6e\u60c5\u5831\u306a\u3057",
"type": "main",
"index": 0
}
]
]
},
"\u30b8\u30aa\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0": {
"main": [
[
{
"node": "\u4f4f\u6240\u30d5\u30a9\u30fc\u30de\u30c3\u30c8",
"type": "main",
"index": 0
}
]
]
},
"\u4f4f\u6240\u30d5\u30a9\u30fc\u30de\u30c3\u30c8": {
"main": [
[
{
"node": "Gemini\u30ea\u30af\u30a8\u30b9\u30c8\u6e96\u5099",
"type": "main",
"index": 0
}
]
]
},
"\u4f4d\u7f6e\u60c5\u5831\u306a\u3057": {
"main": [
[
{
"node": "Gemini\u30ea\u30af\u30a8\u30b9\u30c8\u6e96\u5099",
"type": "main",
"index": 0
}
]
]
},
"Gemini\u30ea\u30af\u30a8\u30b9\u30c8\u6e96\u5099": {
"main": [
[
{
"node": "Gemini Vision API",
"type": "main",
"index": 0
}
]
]
},
"Gemini Vision API": {
"main": [
[
{
"node": "\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u69cb\u7bc9",
"type": "main",
"index": 0
}
]
]
},
"\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u69cb\u7bc9": {
"main": [
[
{
"node": "Dify\u767b\u9332",
"type": "main",
"index": 0
}
]
]
},
"Dify\u767b\u9332": {
"main": [
[
{
"node": "\u7d50\u679c\u51fa\u529b",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"tags": [
"docusearch",
"image-processing"
]
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
httpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Image Processing - DocuSearch. Uses executeWorkflowTrigger, readBinaryFile, httpRequest. Event-driven trigger; 12 nodes.
Source: https://github.com/taiki-aoi/DocuSearch_AI/blob/b341b84f7e1aacb7860e63149ca8759c4d260d52/n8n/workflows/image-processing.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.
02_LLM_Pipeline v1.0. Uses executeWorkflowTrigger, httpRequest, seaTable. Event-driven trigger; 65 nodes.
This template is a powerful, reusable utility for managing stateful, long-running processes. It allows a main workflow to be paused indefinitely at "checkpoints" and then be resumed by external, async
Upload files from any source to your account Kommo or AmoCRM with a simple and reusable workflow. It can split a large file into small ones and upload chunks. Works for Kommo and amoCRM There are 3 re
Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.
Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.