mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
[ACS-11928] convert ReadStream to Blob before appending to FormData (#11987)
* [ACS-11928] convert ReadStream to Blob before appending to FormData * [ACS-11928] comments removed from toFormDataValue * Trigger Build * [ACS-11928] added unit tests and changed the blob variable name to data * [ACS-11928] unit tests updated * [ACS-11928] updated type in multipart form data upload * [ACS-11928] sonar cloud fix
This commit is contained in:
@@ -367,7 +367,12 @@ export class FetchHttpClient implements HttpClient {
|
|||||||
const normalizedParams = FetchHttpClient.normalizeParams(formParams);
|
const normalizedParams = FetchHttpClient.normalizeParams(formParams);
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
for (const [key, value] of Object.entries(normalizedParams)) {
|
for (const [key, value] of Object.entries(normalizedParams)) {
|
||||||
formData.append(key, value as any);
|
const { data, filename } = FetchHttpClient.toFormDataValue(value);
|
||||||
|
if (filename) {
|
||||||
|
formData.append(key, data, filename);
|
||||||
|
} else {
|
||||||
|
formData.append(key, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
@@ -524,4 +529,24 @@ export class FetchHttpClient implements HttpClient {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static toFormDataValue(value: any): { data: any; filename?: string } {
|
||||||
|
if (value && typeof value === 'object' && value.path && typeof value.path === 'string' && !(value instanceof Blob)) {
|
||||||
|
try {
|
||||||
|
const nodeFs = Function('return require("fs")')();
|
||||||
|
const nodePath = Function('return require("path")')();
|
||||||
|
const buffer = nodeFs.readFileSync(value.path);
|
||||||
|
const filename: string = nodePath.basename(value.path);
|
||||||
|
return { data: new Blob([buffer]), filename };
|
||||||
|
} catch {
|
||||||
|
return { data: value };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof Buffer === 'function' && value instanceof Buffer) {
|
||||||
|
return { data: new Blob([value]) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { data: value };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
import { FetchHttpClient } from '../src/fetchHttpClient';
|
import { FetchHttpClient } from '../src/fetchHttpClient';
|
||||||
import { EventEmitter } from 'eventemitter3';
|
import { EventEmitter } from 'eventemitter3';
|
||||||
import { getGlobalMockAgent, mockHost } from './mockObjects/base.mock';
|
import { getGlobalMockAgent, mockHost } from './mockObjects/base.mock';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
describe('FetchHttpClient', () => {
|
describe('FetchHttpClient', () => {
|
||||||
const host = 'https://127.0.0.1:8080';
|
const host = 'https://127.0.0.1:8080';
|
||||||
@@ -1097,4 +1099,123 @@ describe('FetchHttpClient', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('multipart form data upload', () => {
|
||||||
|
let originalFunction: typeof global.Function;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
originalFunction = global.Function;
|
||||||
|
global.Function = ((code: string) => {
|
||||||
|
if (code.includes('require')) {
|
||||||
|
return () => require(/"([^"]+)"/.exec(code)?.[1] || '');
|
||||||
|
}
|
||||||
|
return originalFunction(code);
|
||||||
|
}) as FunctionConstructor;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
global.Function = originalFunction;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should send Blob when form param is a Blob', async () => {
|
||||||
|
mockHost(host).post('/api/upload').reply(200, { success: true });
|
||||||
|
|
||||||
|
const blob = new Blob(['content'], { type: 'text/plain' });
|
||||||
|
const result = await client.post(
|
||||||
|
host + '/api/upload',
|
||||||
|
{
|
||||||
|
httpMethod: 'POST',
|
||||||
|
queryParams: {},
|
||||||
|
headerParams: {},
|
||||||
|
formParams: { file: blob },
|
||||||
|
bodyParam: null,
|
||||||
|
contentType: 'multipart/form-data',
|
||||||
|
accept: 'application/json',
|
||||||
|
responseType: null,
|
||||||
|
returnType: null
|
||||||
|
},
|
||||||
|
defaultSecurityOptions,
|
||||||
|
emitters
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({ success: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert Buffer to Blob when form param is a Buffer', async () => {
|
||||||
|
mockHost(host).post('/api/upload').reply(200, { success: true });
|
||||||
|
|
||||||
|
const buffer = Buffer.from('file content');
|
||||||
|
const result = await client.post(
|
||||||
|
host + '/api/upload',
|
||||||
|
{
|
||||||
|
httpMethod: 'POST',
|
||||||
|
queryParams: {},
|
||||||
|
headerParams: {},
|
||||||
|
formParams: { file: buffer },
|
||||||
|
bodyParam: null,
|
||||||
|
contentType: 'multipart/form-data',
|
||||||
|
accept: 'application/json',
|
||||||
|
responseType: null,
|
||||||
|
returnType: null
|
||||||
|
},
|
||||||
|
defaultSecurityOptions,
|
||||||
|
emitters
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({ success: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should read file and send as Blob when form param has .path property', async () => {
|
||||||
|
mockHost(host).post('/api/upload').reply(200, { success: true });
|
||||||
|
|
||||||
|
const tmpFile = path.join(__dirname, '__test_upload__.txt');
|
||||||
|
fs.writeFileSync(tmpFile, 'test content');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await client.post(
|
||||||
|
host + '/api/upload',
|
||||||
|
{
|
||||||
|
httpMethod: 'POST',
|
||||||
|
queryParams: {},
|
||||||
|
headerParams: {},
|
||||||
|
formParams: { file: { path: tmpFile } },
|
||||||
|
bodyParam: null,
|
||||||
|
contentType: 'multipart/form-data',
|
||||||
|
accept: 'application/json',
|
||||||
|
responseType: null,
|
||||||
|
returnType: null
|
||||||
|
},
|
||||||
|
defaultSecurityOptions,
|
||||||
|
emitters
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({ success: true });
|
||||||
|
} finally {
|
||||||
|
fs.unlinkSync(tmpFile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should pass through string values when form params are strings', async () => {
|
||||||
|
mockHost(host).post('/api/upload').reply(200, { success: true });
|
||||||
|
|
||||||
|
const result = await client.post(
|
||||||
|
host + '/api/upload',
|
||||||
|
{
|
||||||
|
httpMethod: 'POST',
|
||||||
|
queryParams: {},
|
||||||
|
headerParams: {},
|
||||||
|
formParams: { name: 'test-file', description: 'a test' },
|
||||||
|
bodyParam: null,
|
||||||
|
contentType: 'multipart/form-data',
|
||||||
|
accept: 'application/json',
|
||||||
|
responseType: null,
|
||||||
|
returnType: null
|
||||||
|
},
|
||||||
|
defaultSecurityOptions,
|
||||||
|
emitters
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({ success: true });
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user