简体   繁体   中英

Angular 6 and Node Js AWS S3 File Upload Progress Bar

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?

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.

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! :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM