Browse Source

Fixed JavaScript modules with special characters corrupted when uploading files (#15498)

* Fixed JavaScript modules with special characters not displayed correctly in the editor

* Optimized code

* Fixed approach

* Fixed base64toObj

* Fixed

* Types fix

* Extracted shared bytesToString helper, dropped FileReader spoofing
pull/15825/head
Maksym Tsymbarov 4 months ago
committed by GitHub
parent
commit
c24a52fcc8
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 21
      ui-ngx/src/app/core/utils.ts
  2. 48
      ui-ngx/src/app/shared/components/file-input.component.ts

21
ui-ngx/src/app/core/utils.ts

@ -226,8 +226,24 @@ export function objToBase64(obj: any): string {
}));
}
const textDecoderUtf8 = new TextDecoder('UTF-8', { fatal: true });
const textDecoderLatin1 = new TextDecoder('ISO-8859-1');
export function bytesToString(bytes: Uint8Array): string {
try {
return textDecoderUtf8.decode(bytes);
} catch {
return textDecoderLatin1.decode(bytes);
}
}
export function base64toString(b64Encoded: string): string {
return decodeURIComponent(atob(b64Encoded).split('').map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join(''));
const binary = atob(b64Encoded);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytesToString(bytes);
}
export function objToBase64URI(obj: any): string {
@ -235,8 +251,7 @@ export function objToBase64URI(obj: any): string {
}
export function base64toObj(b64Encoded: string): any {
const json = decodeURIComponent(atob(b64Encoded).split('').map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join(''));
return JSON.parse(json);
return JSON.parse(base64toString(b64Encoded));
}
export function stringToBase64(value: string): string {

48
ui-ngx/src/app/shared/components/file-input.component.ts

@ -38,6 +38,7 @@ import { UtilsService } from '@core/services/utils.service';
import { DialogService } from '@core/services/dialog.service';
import { FileSizePipe } from '@shared/pipe/file-size.pipe';
import { coerceBoolean } from '@shared/decorators/coercion';
import { bytesToString } from '@core/utils';
@Component({
selector: 'tb-file-input',
@ -216,34 +217,39 @@ export class FileInputComponent extends PageComponent implements AfterViewInit,
return;
}
const reader = new FileReader();
reader.onload = () => {
let fileName = null;
let fileContent = null;
let mediaType = null;
if (reader.readyState === reader.DONE) {
fileContent = reader.result;
if (fileContent && fileContent.length > 0) {
if (this.contentConvertFunction) {
fileContent = this.contentConvertFunction(fileContent);
}
fileName = fileContent ? file.name : null;
mediaType = file?.file?.type || null;
}
}
resolve({fileContent, fileName, files: null, mediaType});
};
reader.onerror = () => {
resolve({fileContent: null, fileName: null, files: null, mediaType: null});
};
const onReadError = () => resolve({fileContent: null, fileName: null, files: null, mediaType: null});
if (this.readAsBinary) {
const reader = new FileReader();
reader.onload = () => {
const content = reader.readyState === reader.DONE ? reader.result : null;
resolve(this.buildResult(file, content));
};
reader.onerror = onReadError;
reader.readAsBinaryString(file.file);
} else {
reader.readAsText(file.file);
file.file.arrayBuffer().then(
buf => resolve(this.buildResult(file, bytesToString(new Uint8Array(buf)))),
onReadError
);
}
});
}
private buildResult(file: flowjs.FlowFile, content: string | ArrayBuffer): any {
let fileContent: any = content;
let fileName = null;
let mediaType = null;
if (fileContent && fileContent.length > 0) {
if (this.contentConvertFunction) {
fileContent = this.contentConvertFunction(fileContent);
}
fileName = fileContent ? file.name : null;
mediaType = file?.file?.type || null;
}
return {fileContent, fileName, files: null, mediaType};
}
private checkMaxSize(file: flowjs.FlowFile): boolean {
return !this.maxSizeByte || file.size <= this.maxSizeByte;
}

Loading…
Cancel
Save