TypeScript: невозможность построчно перебирать загруженный файл (Angular 9)

Я хочу перебирать строку за строкой по загруженному пользователем файлу в моем приложении Angular. Я пробовал подход, изложенный в этом ответе, но я получаю следующая ошибка:

core.js: 6260 ОШИБКА TypeError: this.firstfile.split не является функцией или его возвращаемое значение не может быть повторено в AppComponent.firstfileupload (app.component.ts: 23) в AppComponent_Template_input_changeimport { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { firstfile=null; second_file = null; title = 'first'; constructor(private http:HttpClient){ } firstfileupload(event){ console.log("First file") console.log(event) this.firstfile=event.target.files[0] for(const line of this.firstfile.split(/[\r\n]+/)){ console.log(line) } console.log("First file File has been changed") } secondfile(event){ this.second_file=event.target.files[0]; // for(const line of this.second_file.split(/[\r\n]+/)){ // console.log(line) // } console.log("Second file uploaded") } onUpload(){ console.log("Upload button clicked") // const fd = new FormData(); // fd.append('files',this.firstfile); // fd.append('files',this.second_file); // this.http.post('http://localhost:5000',fd).subscribe(res =>{ // console.log(res) // } // ) } } listener (app.component.html: 2) в executeListenerWithling (core.js: 21815) в wrapListenerIn_markDirtyAndPreventDefault (core.js: 21857) в HTMLInputElement. (platform-browser.js: 976) в ZoneDelegate.invokeTask (zone-evergreen.js: 399) в Object.onInvokeTask (core.js: 41640) в ZoneDelegate.invokeTask (zone-evergreen.js: 398) в Zone.runTask (zone-evergreen.js: 167) в ZoneTask.invokeTask [как вызываемый] (zone-evergreen.js: 480)

Мой код для app.component.ts

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  firstfile=null;
  second_file = null;
  title = 'first';

  constructor(private http:HttpClient){

  }

  firstfileupload(event){
    console.log("First file")
    console.log(event)
    this.firstfile=event.target.files[0]
    for(const line of this.firstfile.split(/[\r\n]+/)){
      console.log(line)
    }
    console.log("First file File has been changed")
  }
  secondfile(event){
    this.second_file=event.target.files[0];
    // for(const line of this.second_file.split(/[\r\n]+/)){
    //   console.log(line)
    // }
    console.log("Second file uploaded")
  }
  onUpload(){
    console.log("Upload button clicked")
    // const fd = new FormData();
    // fd.append('files',this.firstfile);
    // fd.append('files',this.second_file);
    // this.http.post('http://localhost:5000',fd).subscribe(res =>{
    //   console.log(res)
    // }

    // )
  }
}

И для app.component.html

<h1>Upload the files</h1>
<input type="file" (change)="firstfileupload($event)">
<input type="file" (change)="secondfile($event)">
<button type="button" (click)="onUpload()">Upload</button>

Как я могу перебрать загруженный файл? Я бы предпочел не сохранять файл, а просто повторять только там. Заранее спасибо.


person Saurav Ahlawat    schedule 17.05.2020    source источник
comment
Отвечает ли это на ваш вопрос? Angular - чтение файла и анализ его содержимого   -  person Heretic Monkey    schedule 17.05.2020
comment
У меня вопрос немного другой. Спасибо за отзыв   -  person Saurav Ahlawat    schedule 17.05.2020
comment
Хотя ответ точно такой же ....   -  person Heretic Monkey    schedule 17.05.2020
comment
Я думаю, что ответ здесь дает гораздо больше ясности и лучшую реализацию, чем тот, что был там. Однако, если вы все еще хотите закрыть это, вы можете.   -  person Saurav Ahlawat    schedule 17.05.2020


Ответы (2)


Вы можете попробовать прочитать содержимое файла с помощью _1 _ . Попробуйте следующее

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { Observable, Subject } from 'rxjs';

export class AppComponent {
  ...

  firstfileupload(event) {
    this.firstfile = event.currentTarget.files[0];

    this.readFileContent(event.currentTarget.files[0]).subscribe(
      content => {
        for(const line of content.split(/[\r\n]+/)) {
          if (line !== '') {          // <-- regex pattern might return an empty line at the EOF
            console.log(line);
          }
        }
      }
    );

    console.log("First file File has been changed")
  }

  private readFileContent(file): Observable<any> {
    let result = new Subject<any>();           // <-- Step 1: Create an empty RxJS `Subject`

    const reader = new FileReader();           // <-- Step 2: Create a `FileReader` object
    reader.onload = (e) => {                   // <-- Step 5: Callback function to trigger on the evnet `onload`
      const fileContent = e.target.result;     // <-- Step 6: `event.target.result` contains the file content
      result.next(fileContent);                // <-- Step 7: Push the file contents to the `result` subject
    };
    reader.readAsText(file);                   // <-- Step 3: Read the file using `FileReader`'s method `readAsText`

    return result.asObservable();              // <-- Step 4: Return the `result` subject
  }
}

FileReader является частью File API. Он содержит следующие события, которые запускаются в зависимости от их соответствующих действий.

+------------+----------------------------------------------------------------+
| Event name | Fired when…                                                    |
+------------+----------------------------------------------------------------+
| loadstart  | When the read starts.                                          |
| progress   | While reading (and decoding) blob                              |
| abort      | When the read has been aborted.                                |
|            | For instance, by invoking the abort() method.                  |
| error      | When the read has failed (see file read errors).               |
| load       | When the read has successfully completed.                      |
| loadend    | When the request has completed (either in success or failure). |
+------------+----------------------------------------------------------------+

Мы создаем объект и читаем содержимое файла, используя функцию обратного вызова для события load. Поскольку обработка данных является асинхронной, мы используем субъект RxJS для асинхронного чтения данных, возвращаемых функцией readFileContent.

Вы можете узнать больше об асинхронных данных здесь: https://stackoverflow.com/a/14220323/6513921

person Michael D    schedule 17.05.2020
comment
Но не могли бы вы подробнее рассказать мне о своем коде? Это readFileContent я не понял, если бы вы могли объяснить или порекомендовать мне какой-нибудь учебник, чтобы я мог лучше понять его, это мне очень помогло бы. - person Saurav Ahlawat; 17.05.2020
comment
Я добавил некоторые пояснения и приложил несколько источников. - person Michael D; 17.05.2020
comment
Можете ли вы направить меня по какой-либо ссылке, где я могу узнать, как отображать содержимое файла? - person Saurav Ahlawat; 17.05.2020

Ваша проблема, основанная на ошибке this.firstfile.split is not a function or its return value is not iterable, заключается в том, что вы пытаетесь перебрать объект (т.е. файл), а не его содержимое.

firstfileupload(event){
    . . .
    this.firstfile=event.target.files[0]  // <<<----- You recover the file. As OBJECT
    for(const line of this.firstfile.split(/[\r\n]+/)){ // <<<--- You want to iterate the OBJECT like it is an STRING element
      . . .
    }
    . . .
  }

Вам нужно использовать помощник FileReader для итерации содержимого файла.

Проверьте это: Angular - прочтите файл и проанализируйте его содержимое

person Sergio    schedule 17.05.2020