chore: Share the binary-file node helper between execution contexts (#39473)

Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com>
This commit is contained in:
n8n-cat-bot[bot] 2026-09-24 13:49:29 +00:00 committed by GitHub
parent edf112cd92
commit 7edb12df2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 22 deletions

View File

@ -24,7 +24,7 @@ import { BaseExecuteContext } from './base-execute-context';
import {
assertBinaryData,
getBinaryDataBuffer,
copyBinaryFile,
getNodeBinaryHelperFunctions,
getBinaryHelperFunctions,
detectBinaryEncoding,
} from './utils/binary-helper-functions';
@ -109,16 +109,7 @@ export class ExecuteContext extends BaseExecuteContext implements IExecuteFuncti
detectBinaryEncoding: (buffer: Buffer) => detectBinaryEncoding(buffer),
};
this.nodeHelpers = {
copyBinaryFile: async (filePath, fileName, mimeType) =>
await copyBinaryFile(
this.workflow.id,
this.additionalData.executionId!,
filePath,
fileName,
mimeType,
),
};
this.nodeHelpers = getNodeBinaryHelperFunctions(this.workflow, this.additionalData);
this.getNodeParameter = ((
parameterName: string,

View File

@ -24,6 +24,7 @@ import {
detectBinaryEncoding,
getBinaryDataBuffer,
getBinaryHelperFunctions,
getNodeBinaryHelperFunctions,
prepareBinaryData,
setBinaryDataBuffer,
} from '../binary-helper-functions';
@ -1160,6 +1161,27 @@ describe('copyBinaryFile', () => {
binaryDataService.copyBinaryFile.mockResolvedValueOnce(binaryData);
});
it('should read the workflow and execution IDs when the node helper runs', async () => {
const additionalData = mock<IWorkflowExecuteAdditionalData>();
const { copyBinaryFile: copy } = getNodeBinaryHelperFunctions(
{ id: workflowId },
additionalData,
);
additionalData.executionId = executionId;
await expect(copy(filePath, fileName, 'application/octet-stream')).resolves.toBe(binaryData);
expect(binaryDataService.copyBinaryFile).toHaveBeenCalledWith(
{ type: 'execution', workflowId, executionId },
{
...binaryData,
fileExtension: 'bin',
fileType: undefined,
mimeType: 'application/octet-stream',
},
filePath,
);
});
it('should handle files without explicit mime type', async () => {
const result = await copyBinaryFile(workflowId, executionId, filePath, fileName);

View File

@ -236,6 +236,14 @@ export async function copyBinaryFile(
);
}
export const getNodeBinaryHelperFunctions = (
workflow: { id: string },
additionalData: IWorkflowExecuteAdditionalData,
) => ({
copyBinaryFile: async (filePath: string, fileName: string, mimeType?: string) =>
await copyBinaryFile(workflow.id, additionalData.executionId!, filePath, fileName, mimeType),
});
/**
* Takes a buffer and converts it into the format n8n uses. It encodes the binary data as
* base64 and adds metadata.

View File

@ -24,7 +24,10 @@ import type {
import { UnexpectedError, createEmptyRunExecutionData } from 'n8n-workflow';
import { NodeExecutionContext } from './node-execution-context';
import { copyBinaryFile, getBinaryHelperFunctions } from './utils/binary-helper-functions';
import {
getBinaryHelperFunctions,
getNodeBinaryHelperFunctions,
} from './utils/binary-helper-functions';
import { getInputConnectionData } from './utils/get-input-connection-data';
import { getRequestHelperFunctions } from './utils/request-helper-functions';
import { returnJsonArray } from './utils/return-json-array';
@ -86,16 +89,7 @@ export class WebhookContext extends NodeExecutionContext implements IWebhookFunc
...getBinaryHelperFunctions(additionalData, workflow.id),
};
this.nodeHelpers = {
copyBinaryFile: async (filePath, fileName, mimeType) =>
await copyBinaryFile(
this.workflow.id,
this.additionalData.executionId!,
filePath,
fileName,
mimeType,
),
};
this.nodeHelpers = getNodeBinaryHelperFunctions(this.workflow, this.additionalData);
}
async getCredentials<T extends object = ICredentialDataDecryptedObject>(type: string) {