Búsqueda de sitios web

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.