Как заставить FileReader работать с Angular2?

Как заставить FileReader работать с Angular2!!

При чтении файла с клиентской стороны Angular2 и Typescript,

Я пытаюсь использовать FileReader таким образом:

var fileReader = new FileReader();
fileReader.onload = function(e) {
    console.log("run fileReader.onload");
   //  ......
}

Но это вообще не работает, эта функция "fileReader.onload" никогда не будет вызвана.

На самом деле нужно решение для чтения файлов, пожалуйста, помогите. Благодаря

Проверьте это из интерактивной среды IDE:

Предварительный просмотр: https://angular2-butaixianran.c9.io/src/index.html

Редактор: https://ide.c9.io/butaixianran/angular2

Ответ 1

Сначала вы должны указать цель события изменения в форме ввода в шаблоне:

@View({
  template:`
    <div>
      Select file:
      <input type="file" (change)="changeListener($event)">
    </div>
  `
})

Как вы можете видеть, я привязал метод changeListener() к событию (change). Моя реализация класса:

  changeListener($event) : void {
    this.readThis($event.target);
  }

  readThis(inputValue: any) : void {
    var file:File = inputValue.files[0]; 
    var myReader:FileReader = new FileReader();

    myReader.onloadend = function(e){
      // you can perform an action with readed data here
      console.log(myReader.result);
    }

    myReader.readAsText(file);
  }

Listener передает файл из события в метод readThis. Прочтите это, внедрив собственный FileReader. Вы также можете определить FileReader в компоненте вместо функции.

Ответ 2

Ответ от @haz111 уже работает, но на всякий случай вы хотите сделать файловый читатель повторно используемым компонентом, вы могли бы использовать это или лучше: улучшите это:

inputfilereader.ts

import {Component, ElementRef, EventEmitter} from 'angular2/angular2';

@Component({
    selector: 'filereader',
    templateUrl: './commons/inputfilereader/filereader.html',
    styleUrls: ['./commons/inputfilereader/filereader.css'],
    providers: [ElementRef],
    events : ['complete']
})

export class InputFileReader {
    complete :EventEmitter = new EventEmitter();

    constructor(public elementRef: ElementRef) {
    }

    resultSet:any; // dont need it 

    changeListener($event: any) {
        var self = this;
        var file:File = $event.target.files[0];
        var myReader:FileReader = new FileReader();
        myReader.readAsText(file);
        var resultSet = [];
        myReader.onloadend = function(e){
            // you can perform an action with data read here
            // as an example i am just splitting strings by spaces
            var columns = myReader.result.split(/\r\n|\r|\n/g);

            for (var i = 0; i < columns.length; i++) {
                resultSet.push(columns[i].split(' '));
            }

            self.resultSet=resultSet; // probably dont need to do this atall
            self.complete.next(self.resultSet); // pass along the data which would be used by the parent component
        };
    }
}

filereader.html

<input type="file" (change)="changeListener($event)" />

Использование в других файлах

anotherfile позволяет сказать dfs.ts

import {Component, ElementRef} from 'angular2/angular2';
import {InputFileReader} from '../../commons/inputfilereader/inputfilereader';

@Component({
    selector: 'dfs',
    templateUrl: './components/dfs/dfs.html',
    styleUrls: ['./components/dfs/dfs.css'],
    providers: [ElementRef],
    directives:[InputFileReader]
})

export class DfsCmp {
    constructor(public eleRef :ElementRef) {}

    callSomeFunc(data):void {
        console.log("I am being called with ", data);
    }
}

dfs.html

<filereader (complete)="callSomeFunc($event)"></filereader> 

Ответ 3

Просто добавьте

fr.readAsText(event.files[0]);

После определения onLoad.

Возможно, это может вам помочь, это моя функция обработчика загрузки для библиотеки загрузки файлов primeng

archivoUploadHandler(event) {
  let contenido;
  let fr = new FileReader();
  fr.onload = (e) => {
    contenido = fr.result;
    console.log(contenido);
  };
  fr.readAsText(event.files[0]);
}

Ответ 4

немного опоздал на вечеринку здесь. Это также можно сделать, создав FileReader как сервис. Это поможет модульным тестам и отделит FileReader от компонента, который его использует.

вы можете создать токен следующим образом:

export const FileReaderService = new InjectionToken<FileReader>('FileReader', {
  factory: () => new FileReader(),
});

И тогда вы можете использовать его следующим образом: (Я считаю, что его можно использовать как обычный сервис. Я еще не тестировал его. Но способ, которым я здесь показываю, работает просто отлично)

class MyService { // this could be a component too
  constructor(@Inject(FileReaderService) private reader: FileReader) {}
  readFile() {
    const file = // the file you want to read
    this.reader.onload = // whateever you need
    this.reader.readAsDataURL(file)
  }
}

Ответ 5

Я хотел бы создать метод, как показано ниже

readFileContent(file: File): Promise<string | ArrayBuffer> {
    return new Promise<string | ArrayBuffer>((resolve, reject) => {

      const myReader: FileReader = new FileReader();

      myReader.onloadend = (e) => {
        resolve(myReader.result);
      };

      myReader.onerror = (e) => {
        reject(e);
      };

      myReader.readAsText(file);
    });
  }

и называть это как

const content = await this.readFileContent(inputValue.files[0])