fix(Microsoft OneDrive Node): Try to download file using downloadUrl (#13200)

Co-authored-by: Michael Kret <michael.k@radency.com>
This commit is contained in:
Shireen Missi 2025-02-12 12:46:21 +00:00 committed by GitHub
parent 56426e989f
commit 67cd05c6dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 106 additions and 12 deletions

View file

@ -1,3 +1,4 @@
import { IncomingMessage } from 'http';
import type { import type {
IDataObject, IDataObject,
IExecuteFunctions, IExecuteFunctions,
@ -105,6 +106,7 @@ export class MicrosoftOneDrive implements INodeType {
responseData = await microsoftApiRequest.call(this, 'GET', `/drive/items/${fileId}`); responseData = await microsoftApiRequest.call(this, 'GET', `/drive/items/${fileId}`);
const fileName = responseData.name; const fileName = responseData.name;
const downloadUrl = responseData['@microsoft.graph.downloadUrl'];
if (responseData.file === undefined) { if (responseData.file === undefined) {
throw new NodeApiError(this.getNode(), responseData as JsonObject, { throw new NodeApiError(this.getNode(), responseData as JsonObject, {
@ -117,6 +119,7 @@ export class MicrosoftOneDrive implements INodeType {
mimeType = responseData.file.mimeType; mimeType = responseData.file.mimeType;
} }
try {
responseData = await microsoftApiRequest.call( responseData = await microsoftApiRequest.call(
this, this,
'GET', 'GET',
@ -127,6 +130,17 @@ export class MicrosoftOneDrive implements INodeType {
{}, {},
{ encoding: null, resolveWithFullResponse: true }, { encoding: null, resolveWithFullResponse: true },
); );
} catch (error) {
if (downloadUrl) {
responseData = await this.helpers.httpRequest({
method: 'GET',
url: downloadUrl,
returnFullResponse: true,
encoding: 'arraybuffer',
json: false,
});
}
}
const newItem: INodeExecutionData = { const newItem: INodeExecutionData = {
json: items[i].json, json: items[i].json,
@ -146,10 +160,15 @@ export class MicrosoftOneDrive implements INodeType {
items[i] = newItem; items[i] = newItem;
const data = Buffer.from(responseData.body as Buffer); let data;
if (responseData?.body instanceof IncomingMessage) {
data = responseData.body;
} else {
data = Buffer.from(responseData.body as Buffer);
}
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData( items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(
data as unknown as Buffer, data,
fileName as string, fileName as string,
mimeType, mimeType,
); );

View file

@ -0,0 +1,75 @@
import type { IncomingMessage } from 'http';
import type { MockProxy } from 'jest-mock-extended';
import { mock } from 'jest-mock-extended';
import { type IHttpRequestMethods, type IExecuteFunctions, ApplicationError } from 'n8n-workflow';
import * as genericFunctions from '../../GenericFunctions';
import { MicrosoftOneDrive } from '../../MicrosoftOneDrive.node';
jest.mock('../../GenericFunctions', () => ({
...jest.requireActual('../../GenericFunctions'),
microsoftApiRequest: jest.fn(async function (_: IHttpRequestMethods, resource: string) {
if (resource === '/drive/items/fileID') {
return {
name: 'MyFile',
'@microsoft.graph.downloadUrl': 'https://test.com/file',
file: {
mimeType: 'image/png',
},
};
}
if (resource === '/drive/items/fileID/content') {
throw new ApplicationError('Error');
}
}),
}));
describe('Test MicrosoftOneDrive, file > download', () => {
let mockExecuteFunctions: MockProxy<IExecuteFunctions>;
let microsoftOneDrive: MicrosoftOneDrive;
const httpRequest = jest.fn(async () => ({ body: mock<IncomingMessage>() }));
const prepareBinaryData = jest.fn(async () => ({ data: 'testBinary' }));
beforeEach(() => {
mockExecuteFunctions = mock<IExecuteFunctions>();
microsoftOneDrive = new MicrosoftOneDrive();
mockExecuteFunctions.helpers = {
httpRequest,
prepareBinaryData,
returnJsonArray: jest.fn((data) => [data]),
constructExecutionMetaData: jest.fn((data) => data),
} as any;
});
afterEach(() => {
jest.clearAllMocks();
});
it('should call helpers.httpRequest when request to /drive/items/{fileId}/content fails', async () => {
const items = [{ json: { data: 'test' } }];
mockExecuteFunctions.getInputData.mockReturnValue(items);
mockExecuteFunctions.getNodeParameter.mockImplementation((key: string) => {
if (key === 'resource') return 'file';
if (key === 'operation') return 'download';
if (key === 'fileId') return 'fileID';
if (key === 'binaryPropertyName') return 'data';
});
const result = await microsoftOneDrive.execute.call(mockExecuteFunctions);
expect(genericFunctions.microsoftApiRequest).toHaveBeenCalledTimes(2);
expect(httpRequest).toHaveBeenCalledTimes(1);
expect(httpRequest).toHaveBeenCalledWith({
encoding: 'arraybuffer',
json: false,
method: 'GET',
returnFullResponse: true,
url: 'https://test.com/file',
});
expect(prepareBinaryData).toHaveBeenCalledTimes(1);
expect(result).toEqual([
[{ binary: { data: { data: 'testBinary' } }, json: { data: 'test' } }],
]);
});
});