I am unclear how the kendo upload communicates with the server to get the progress indicator. In my application the progress indicator always goes from directly from 0% to complete regardless of file size. I have the S3Helper on the server logging status but I don't know how to make that status known to the client.
Upload Service
using Microsoft.AspNetCore.Cors;using Microsoft.AspNetCore.Identity;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Rendering;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.Logging;using Microsoft.Extensions.Options;using Newtonsoft.Json;using Newtonsoft.Json.Linq;using System.Threading;using System.Threading.Tasks;using ARLNService.Helpers;using ARLNService.Models;using ARLNService.Services;using System;using Microsoft.AspNetCore.Authentication;using Microsoft.AspNetCore.Authorization;using System.Collections.Generic;using Microsoft.AspNetCore.Http;using System.IO;using OfficeOpenXml;using System.Linq;using System.Data.SqlClient;namespace ARLNService.Controllers{ [EnableCors("MyPolicy")] [ApiController] [ApiVersionNeutral] [Route("api/[controller]/[action]")] public class UploadFilesController : Controller { private readonly IConfiguration _configuration; private readonly ARLNServiceContext _db; public UploadFilesController( IConfiguration configuration, ARLNServiceContext db) { _configuration = configuration; _db = db; } [HttpPost] public async Task<IActionResult> UploadFile(IList<IFormFile> files) { String bucket = _configuration["AWS:bucket"]; String accessKey = _configuration["AWS:AWS_ACCESS_KEY_ID"]; System.DateTime thisDay = System.DateTime.Now; // I'm getting file inside Request object var file = this.Request.Form.Files[0]; // create unique file name for prevent the mess var fileName = Guid.NewGuid() + file.FileName; string userName = this.Request.Form["userName"].ToString(); Upload upload = new Upload(); upload.fileName = fileName; upload.uploadDate = thisDay; upload.userName = userName; upload.originalFileName = file.FileName; _db.Set<Upload>().Add(upload); _db.SaveChanges(); var fileResponse = await S3Service.UploadObject(file, fileName, bucket, fileName, userName); Upload uploadUpdate = _db.Uploads.FirstOrDefault(c => c.fileName == fileName); if (fileResponse.success == true) { uploadUpdate.uploadStatus = "Uploaded"; _db.SaveChanges(); return Ok(); } else { uploadUpdate.uploadStatus = "Upload Failed"; _db.SaveChanges(); return BadRequest("Failed to upload file"); } } }}
Helper function for S3
using System;using System.IO;using System.Threading.Tasks;using Amazon.S3;using Amazon.S3.Model;using ARLNService.Models;using Microsoft.AspNetCore.Http;using System.Collections.Generic;using System.Security.Cryptography;using Microsoft.AspNetCore.Mvc;using Amazon.S3.Transfer;namespace ARLNService.Helpers{ public class S3Service { public async static Task<UploadFile> UploadObject(IFormFile file, String fileName, String bucket, String accessKey, String userName) { // connecting to the client var client = new AmazonS3Client(); // get the file and convert it to the byte[] byte[] fileBytes = new Byte[file.Length]; file.OpenReadStream().Read(fileBytes, 0, Int32.Parse(file.Length.ToString())); try { using (System.IO.MemoryStream filestream = new System.IO.MemoryStream(fileBytes)) { using (Amazon.S3.Transfer.TransferUtility tranUtility = new Amazon.S3.Transfer.TransferUtility(client)) { var request = new TransferUtilityUploadRequest { BucketName = bucket, Key = accessKey, InputStream = filestream }; request.Metadata.Add("userName", userName); request.UploadProgressEvent += new EventHandler<UploadProgressArgs> (uploadRequest_UploadPartProgressEvent); await tranUtility.UploadAsync(request); } } return new UploadFile { success = true, fileName = fileName }; } catch (Exception e) { return new UploadFile { success = false, fileName = fileName }; } } static void uploadRequest_UploadPartProgressEvent(object sender, UploadProgressArgs e) { // Process event. Console.WriteLine("{0}/{1}", e.TransferredBytes, e.TotalBytes); } }}
Angular Component
<div class="filters " (click)="activate()"> <div class="confirmMessage"> <p>Choose select file to upload a .csv file.</p> </div> <div class="dropdownSection"> <kendo-upload #myUpload="kendoUpload" [saveUrl]="uploadSaveUrl" (upload)="uploadEventHandler($event)" (success)="loadItems($event)" [removeUrl]="uploadRemoveUrl" [restrictions]="myRestrictions" [multiple]="false" [accept]="acceptString"> <kendo-upload-messages select="Select file..."> </kendo-upload-messages> </kendo-upload> <br /> </div></div><div class="clearfix"></div>
Angular code
import { Component, OnDestroy, OnInit, Output, EventEmitter, ChangeDetectorRef, Injector, ViewEncapsulation } from '@angular/core';import { FormControl } from "@angular/forms";import { Subscription } from 'rxjs/Subscription';import { IPageInfo, IMetadata, IEntry, IRootObject } from '../../models/eipMessage';import { DataService } from '../../shared/data.services';import { UtilService } from '../../shared/util.service';import { UtilityService } from '../../shared/utility.service';import { ErrorMessageService } from '../../shared/error-message.service';import { GlobalService } from '../../shared/global.service';import { MatDatepicker, MatDatepickerInput, MatDatepickerToggle } from '@angular/material';import * as _ from 'lodash';import { FileRestrictions, UploadEvent, FileState } from '@progress/kendo-angular-upload';import { environment } from '../../../environments/environment';import { Observable, of, concat } from 'rxjs';import { delay } from 'rxjs/operators';@Component({ selector: 'uploads-file-select', templateUrl: 'uploads-file-select.component.html', styleUrls: ['uploads-file-select.component.scss']})export class UploadsFileSelectComponent implements OnInit, OnDestroy { public acceptString = ".txt, .csv"; public uploadSaveUrl = environment.serviceUrl + "api/UploadFiles/UploadFile"; // should represent an actual API endpoint myRestrictions: FileRestrictions = { allowedExtensions: ['.csv', '.txt'] }; @Output() fileUploaded = new EventEmitter(); constructor(private utilityService: UtilityService, private dataService: DataService, private errMsgService: ErrorMessageService, private injector: Injector, private changeRef: ChangeDetectorRef, private utilService: UtilService, private globalService: GlobalService) { } uploadEventHandler(e: UploadEvent) { e.data = { userName: "tester@lab.com" }; } public remove(upload, uid: string) { console.log("remove" + uid); upload.removeFilesByUid(uid); } public loadItems(event) { console.log("load itemas"); this.fileUploaded.emit(); } ngOnInit() { } ngOnDestroy() { } activate() { };}