angular - Cómo manejar que FileReader devuelve ya sea ArrayBuffer o String en TypeScript
Me he estado persiguiendo en círculos y ahora es momento de pedir ayuda. Tengo el siguiente servicio (Typescript) que abre un lector de archivos, y dependiendo del tipo de archivo, llama a readAsText() o readAsArrayBuffer(). Tengo una clase envoltorio (MyDocument) para el texto que devolverá el fileReader, así como algunos metadatos sobre el documento. En la clase MyDocument, defino un campo llamado docContent: string. Aquí es donde comienzan los problemas. Debido a la instrucción condicional if (resaltada en el código) que elige entre readAsText o readAsArrayBuffer, al compilador no le gusta la asignación de los resultados del fileReader a docContent porque PODRÍA ser un string o un ArrayBuffer. Así que modifico el campo para que sea: docContent: string | ArrayBuffer pensando en lo listo que soy. PERO ahora que el campo puede ser un string o un ArrayBuffer, el compilador no me deja manipular el campo docContents (como split('\n') porque split no pertenece a ArrayBuffer. Sé que debe haber una solución más elegante al problema, pero estoy demasiado cerca como para verlo claramente. Agradecería cualquier ayuda.
public readFile(files: FileList): MyDocument {
this.myDocument = new MyDocument();
if (files && files[0] && files[0].size > 0) {
this.fileToRead = files[0];
this.myDocument.fileName = this.fileToRead.name;
this.myDocument.fileSize = this.fileToRead.size;
this.myDocument.fileType = this.fileToRead.type;
}
else {
const message = "Either no file selected, or file has zero size";
confirm(message);
}
if (this.fileToRead) {
var fr = new FileReader();
fr.onloadend = () => {
if (this.myDocument.fileType == "text/plain") {
this.myDocument.docContents = fr.result;
} else {
let extractedText = this.extractTextUsingSolr(fr.result);
}
}
***if (this.fileToRead.type == 'text/plain') {
fr.readAsText(this.fileToRead);
}
else {
fr.readAsArrayBuffer(this.fileToRead);
}***
return this.myDocument;
}
else {
console.log('No file selected!');
return;
}
}
~
Solo para ser completos, aquí está la clase MyDocument, y cuando intento hacer docContents.split("\n") es donde el compilador se quejó.
export class MyDocument {
fileName: string;
fileType: string;
fileSize: number;
numWords: number;
numSents: number;
docWords: string[];
docContents: string | ArrayBuffer;
processDocument(): void {
const sents = [];
const lines = this.docContents.split("\n");
let sentWords = [];
}
}
Respuesta #1
solución rápida
if (typeof this.docContents === 'string') {
lines = this.docContents.split("\n");
} else {
// dealing with ArrayBuffer
// google on methods in ArrayBuffer object you can use
}
pero personalmente no me gusta ese enfoque. Usaría 2 propiedades diferentes con nombres diferentes. Una para ArrayBuffer, otra para cadena de texto.
