3

I'm trying to upload a csv file using ng-file-upoad. Here is my code snippet:

Upload.upload({
   url: baseUrl + '/file-upload',
   data: {
      file: file
   }
 })
 .then(function(res) {
    console.log('success: ===> ', res);
 }, function(err) {
    console.log('erroir: ===> ', err);
 }, function() {
    console.log('progress: ', arguments);
 });

And in node environment I'm parsing the file and inserting the data in database. I don't want to close the connection. That's why I used "response.write". Here is my code snippet:

var path = req.files.file.path,
    currentIndex = 0;

fs.readFile(path, 'utf8', function(err, data) { 
    if(err) {
         // handle error
    } else {
        // making array (dataArray) from data
        dataArray.forEach(function(eachData){
            newEntry = new app.db.models.SomeCollection(eachData);
            newEntry.save(function(err, data) {
              if (currentIndex === dataArray.length) {
                 res.end('DONE!');
              } else {
                  currentIndex++;
                  res.write(JSON.stringify({
                     total: dataArray.length,
                     done: currentIndex
                  }));
              }
            });
        })
    }
});

My question is how I will get the data I'm passing in "res.write"? I don't want to use socket for only this purpose. Am I missing something?

Kaushick Gope
  • 154
  • 1
  • 11
  • What do you mean by "I don't want to close the connection"? – Alexandr Lazarev Dec 17 '15 at 12:04
  • I don't want to use response.send or response.end. Actually the file contains 5000 data, and I want to show a progress bar depends on the response from server. Is there any way to send data from server except socket? – Kaushick Gope Dec 17 '15 at 12:25
  • 1
    The connection made by ajax requests will close once you send the response back. Otherwise you've to use socket connection. *"I don't want to use socket for only this purpose"* - what else is the purpose of socket connection..? Your only closest option will be to implement long polling – T J Dec 17 '15 at 12:25
  • You can't do it with a single `http` request. Or you should create a socket and pipe a stream there, or you should make many `http` requests from the client to the server. – Alexandr Lazarev Dec 17 '15 at 13:08
  • I know this is an old question, but I'm facing the same problem right now. Have you found the answer since then? – Nelson Teixeira Jun 11 '20 at 06:30

2 Answers2

1

As already explained here:

response.send(msg) is equal to response.write(msg);response.end();

Which means, send can only be called once, write can be called many times, but you must call end yourself.

You are probably not receiving the response because response.end() is missing.

Once you end() your response you should be able to access the response data in your angular controller in the Upload.upload promise that is returned.

It's not like close a connection as you said. This is not a socket-ish like implementation (such as ws or socket.io). Once a request is made it should have a response even if it is to provide error details about that request (i.e. status 401, 403, 404, etc).

Community
  • 1
  • 1
pgrodrigues
  • 2,083
  • 1
  • 24
  • 28
  • I've checked that link. But I don't want to use response.send or response.end. Actually the file contains 5000 data, and I want to show a progress bar depends on the response from server. Is there any way to send data from server? – Kaushick Gope Dec 17 '15 at 12:22
  • Take a look at this blog: http://www.jonahnisenson.com/file-uploads-using-angular-and-nodeexpress/. It is explained how to implement progress during file upload in angular. It is implemented client side not server side. – pgrodrigues Dec 17 '15 at 12:24
  • 1
    I'm not talking about file upload progress. Please read the question properly. I'm working with the data after the file upload is done. I want to show the progress of inserted data, not the upload percentage of the file. – Kaushick Gope Dec 17 '15 at 12:28
0

in your angular component:

  ...
  constructor(private incrementalService: IncrementalService) {}
   
  incrementalTest() { //activate with a button or whatnot
    this.incrementalService.increment().subscribe( (result:any) => {
      if (result.partialText) {
        console.log(partialText); //do whatever you need to do with your partial results here!
      }
    })
  }

your angular service:

   import { HttpClient, HttpHeaders } from '@angular/common/http';
   public class IncrementalService {

     constructor(private http: HttpClient) {}

     increment(): Observable<ArrayBuffer> {
        const options = {
          reportProgress: true,
          responseType: 'text',
          observe: 'events'
        }
        return this.http.request('get', 'http://someURL', { ...this.addRawHeaderOptions(), ...options});
     }

     private addRawHeaderOptions() {
        const authHeaders = new HttpHeaders({
          'Content-Type': 'application/json',
          //authorization, Cache-Control: 'no-cache, Pragma:'no-cache', et al.     }
        return { headers: authHeaders }
     }
   }

Finally, your back-end service (this is express, but should work similarly for raw node):

  async function(request, response) {
    const increments = [ 1,2,3,4 ];
    response.set('Content-Type', 'text/html');
    for (const value of increments) { //contains async call - not switch-outable for a forEach.
      response.write(`increment - ${value} `);
      const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
      await delay(1000)
    }
    response.status(200).end()
  }

browser console output when run:

  • increment - 1
  • increment - 1 increment - 2
  • increment - 1 increment - 2 increment - 3
  • increment - 1 increment - 2 increment - 3 increment - 4

!!Sorry for any typos - i had to transcribe this from a locked-down machine.