1

I'm trying to create a progress bar when uploading files via Angular 6 (frontend) and NodeJs (backend) to an asw-s3 bucket. How to fetch the progress (or the already uploaded bytes) and receive them in the Angular 6 frontend in realtime?

1

2 Answers 2

2

Not sure if angular has a specific method for this, but here is a working example I used in some of my angular based websites :

sendFile(file) {
    let formData: FormData = new FormData();
    formData.append('my_file', file);

    let xhr = new XMLHttpRequest();
    xhr.upload.onprogress = function (progEvent: ProgressEvent) {
        if (progEvent.lengthComputable) {
            var uploadedSoFar = (progEvent.loaded / progEvent.total) * 100;
            console.log("Uploaded: " + uploadedSoFar + "% ")
            if (progEvent.loaded == progEvent.total){
                // uploaded up to 100%
            }
        }

    };
    xhr.open("POST", `/your_site`, true);
    xhr.send(formData);
}

Some explanation of what is going on :

FormData

The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest.send() method. It uses the same format a form would use if the encoding type were set to "multipart/form-data"

https://developer.mozilla.org/en-US/docs/Web/API/FormData

XMLHttpRequest

Use XMLHttpRequest (XHR) objects to interact with servers. You can retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just part of a page without disrupting what the user is doing.

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest

Node Side I'm updating this post to add a node code sample (after the comments). I am not as good in node.js, so my following code is not a good example.

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  // Remove this, I use it for this example to be easy to reproduce
  res.setHeader('X-Frame-Options', 'ALLOWALL');
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'POST, GET');
  res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  if (req.method == 'POST') {
        console.log("Receiving file");
        var body = '';
        req.on('data', function (data) {
            body += data;
            console.log("receiving data : " + body);
        });
        req.on('end', function () {
            console.log("received all the data: " + body);
        });
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('Reception completed');
    }

});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

If you receive data in your node.js, this would mean that your front is working correctly.

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

18 Comments

This really helps! But how would you extract the file from the formData in the backend?
Depends on your backend. in django, you can extract the file from the request : my_file = request.FILES['my_file']. If you want to store it, if you're in python backend : fs = FileSystemStorage(); fs.save(filename, my_file)
I am getting an undefined when accessing req.FILES['file']
What is your backend ?
I am using NodeJs
|
2

you can just upload a file with the regular HttpClient and use the flag reportProgress: true.

Full example:

constructor(private _http: HttpClient,
            private _logger: Logger) {}

this._http
    .post(FILE_UPLOAD_URL, formData, {
          reportProgress: true,
          observe: 'events'
        })
        .subscribe((event: HttpEvent<any>) => {
            switch (event.type) {
                case HttpEventType.Sent:
                    this._logger.debug('Upload started');
                    break;
                case HttpEventType.DownloadProgress:
                    // Live stats are also possible for downloads
                case HttpEventType.UploadProgress:
                    if (event.total) {
                         const progress = Math.round(event.loaded / event.total * 100);
                         const timeElapsed = Date.now() - startTime;
                         const uploadSpeed = event.loaded / (timeElapsed / 1000);
                         const uploadTimeRemaining = Math.ceil(
                                            (event.total - event.loaded) / uploadSpeed
                                        );
                         const uploadTimeElapsed = Math.ceil(timeElapsed / 1000);
                         const uploadSpeed = uploadSpeed / 1024 / 1024;
                         this._logger.debug('Upload stats:', progress, timeElapsed, uploadSpeed, uploadTimeRemaining,  uploadTimeElapsed, uploadSpeed);

                         break;
                     case HttpEventType.Response:
                          this.progressForFile = 100;
                          this._logger.debug('Done! ResponseBody:', event.body);

                 });

If hope, this helps! :-)

1 Comment

This really helped! Unfortunately, the progress does not track the upload progress. It's almost instantly 100% and the upload finishes seconds later.

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.