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() {
};
}