0

I want to iterate line by line over a user uploaded file in my Angular app. I have tried the approach stated in this answer but I get the following error:

core.js:6260 ERROR TypeError: this.firstfile.split is not a function or its return value is not iterable at AppComponent.firstfileupload (app.component.ts:23) at AppComponent_Template_input_change_2_listener (app.component.html:2) at executeListenerWithErrorHandling (core.js:21815) at wrapListenerIn_markDirtyAndPreventDefault (core.js:21857) at HTMLInputElement. (platform-browser.js:976) at ZoneDelegate.invokeTask (zone-evergreen.js:399) at Object.onInvokeTask (core.js:41640) at ZoneDelegate.invokeTask (zone-evergreen.js:398) at Zone.runTask (zone-evergreen.js:167) at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:480)

My code for 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)
    // }

    // )
  }
}

And for 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>

How can I iterate over an uploaded file ? I would rather not save the file and just iterate there only. Thanks in advance.

4
  • Does this answer your question? Angular - Read a file and parse its content Commented May 17, 2020 at 14:25
  • My question is a bit different. Thanks for feedback Commented May 17, 2020 at 14:36
  • The answer is exactly the same though.... Commented May 17, 2020 at 14:37
  • I think the answer here gives much more clarity and better implementation, than the one over there. However, if you still want to close this, you can. Commented May 17, 2020 at 15:17

2 Answers 2

0

You could try to read the contents of the file using FileReader.readAsText(). Try the following

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
  }
}

The FileReader is part of the File API. It contains the following events that are triggered based on their respective actions.

+------------+----------------------------------------------------------------+
| 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). |
+------------+----------------------------------------------------------------+

We are creating the object and reading the contents of the file using the callback function to the load event. Since the data handling is asynchronous, we use a RxJS Subject to read the data returned from the function readFileContent asynchronously.

You could learn more about asynchronous data here: https://stackoverflow.com/a/14220323/6513921

Sign up to request clarification or add additional context in comments.

3 Comments

But can you explain your code a bit more to me ? That readFileContent I didn't understand, if you could explain or refer me to some tutorial so that I can understand it more better , that would help me a lot.
I've added some explanation inline and attached some sources.
Can you refer me to some link where I can learn how to display the contents of a file ?
0

You problem, based on this.firstfile.split is not a function or its return value is not iterable error, is that you are trying to iterate an object (i.e., the file), not its contents.

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
      . . .
    }
    . . .
  }

You need to use the FileReader helper to iterate file contents.

Check this: Angular - Read a file and parse its content

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.