Angular 4+ Kendo Upload example

1 Answer 1973 Views
General Discussions
yamaha
Top achievements
Rank 1
yamaha asked on 29 Nov 2017, 01:45 PM

Hello all,

    I am trying to implement Kendo Upload in my project. Project is at Angular 4.4.6 version. We are having difficulty understanding and finding an example which shows how you send an attachment with a true web service call. 

 

Can you please post an example which shows an example with a true web service call to upload an attachment. 

Thanks,

Akshay

1 Answer, 1 is accepted

Sort by
0
Dimiter Madjarov
Telerik team
answered on 29 Nov 2017, 02:12 PM
Hello Akshay,


We don't have such example available, however any of the examples in our documentation would work with a web service, as the files are uploaded as standard multipart form-data. No Upload specific configuration would be needed.

Regards,
Dimiter Madjarov
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Chau
Top achievements
Rank 1
commented on 21 Mar 2019, 02:52 PM

The kendo-upload with [autoUpload]="false" shows a 'Clear' and 'Upload' button after selecting a file.  Is there a way to associate a click event to the 'Upload' button, so I can add code to call a typescript service (which encapsulates the API endpoint) ?

Thanks!

Dimiter Madjarov
Telerik team
commented on 21 Mar 2019, 03:20 PM

Hi Chau,


Yes, a callback could be executed when the "Upload" button is clicked. To achieve this attach a handler to the upload event of the component

https://www.telerik.com/kendo-angular-ui-develop/components/upload/api/UploadComponent/#toc-upload

Another approach to achieve this task (since the end point should be invoked manually) would be to use an HttpInterceptor to catch the request and insert custom logic before the actual request is initiated.

https://angular.io/api/common/http/HttpInterceptor

Our demos use similar approach to prevent the actual upload process of the files

https://www.telerik.com/kendo-angular-ui-develop/components/upload/

Regards,
Dimiter Madjarov
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Chau
Top achievements
Rank 1
commented on 21 Mar 2019, 09:24 PM

Thanks Dimiter for your quick reply.

I am trying to POST a form-data content-type to my Web Api Controller but on the server, there is no file data attached to the request. Would you have some sample code to show how to post a form-data to the server? I am not sure if I should set content-type to 'multipart/formdata' in the POST request?

Here's is my kendo-upload control definition (note that I removed the [saveUrl] and [removeUrl], since I am using Upload event handler to manually call my upload controller, is that OK?)

<kendo-upload
[autoUpload]="false"
[restrictions]="uploadRestrictions"
(select)="selectEventHandler($event)"
(clear)="clearEventHandler($event)"
(remove)="removeEventHandler($event)"
(complete)="completeEventHandler($event)"
(upload)="uploadEventHandler($event)">
</kendo-upload>

in my .ts file, the selectEventHandler function is setting the property currentFileUpload:

public selectEventHandler(e: SelectEvent): void {
    const that = this;
    e.files.forEach((file) => {
         console.log(`File selected: ${file.name}`);
         if (!file.validationErrors) {
              this.currentFileUpload = file;

         }

  });

the uploadEventHandler function is calling my fileservice method UploadFile():

uploadEventHandler(e: UploadEvent) {
// alert('file uploaded=' + e.files[0].name);
this.fileservice.isLoading = true;
this.fileservice.uploadFile(this.currentFileUpload);
}

My fileservice.service.ts has a function uploadFile and constructor as:

constructor(private httpclient: HttpClient) {
}

uploadFile(file: File): any {
   const formdata: FormData = new FormData();
   formdata.append('file', file);                                     //the uploaded file content
   formdata.append('documentVersionId', '123');       //I need to pass some additional info to the server besides the File data

   const apiURL = this.api_path + 'Upload';     //calling http://localhost:52333/api/UploadController

   const uploadReq = new HttpRequest('POST', apiURL, formdata, {
      reportProgress: true
   });
   this.httpclient.request(uploadReq).subscribe(event => {
      if (event.type === HttpEventType.UploadProgress) {
          this.progress = Math.round(100 * event.loaded / event.total);
      }
  });

}

On the server side, the api controller class POST method does not get any file data in the HttpContext.Current.Request, ie. httpRequest.Files.Count = 0.

If I checked HttpContext.Current.Request.Form in debug window, I saw two keys: file and documentVersionId.

 

public class UploadController : ApiController
{

        [HttpPost]
        public HttpResponseMessage Post()
        {
           
            HttpResponseMessage result = null;
            var httpRequest = HttpContext.Current.Request;
            if (httpRequest.Files.Count > 0)     // ==> THERE IS NO FILE attached here
            {
                var docfiles = new List<string>();
                foreach (string file in httpRequest.Files)
                {
                    var postedFile = httpRequest.Files[file];
                    var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
                    postedFile.SaveAs(filePath);
                    docfiles.Add(filePath);
                }
                result = Request.CreateResponse(HttpStatusCode.Created, docfiles);
            }
            else
            {
                result = Request.CreateResponse(HttpStatusCode.BadRequest);
            }
            return result;
        }

 

Dimiter Madjarov
Telerik team
commented on 25 Mar 2019, 08:55 AM

Hello Chau,


It looks like that in the current implementation, the whole file information (i.e. size, extension, validation errors etc.) is passed to the custom upload service. It is wrapped in a FileInfo interface

https://www.telerik.com/kendo-angular-ui/components/upload/api/FileInfo/ 

The specific file data is contained in the rawFile property, which is the actual file that should be uploaded.

As for the server side implementation, there is no Kendo UI specific implementation that is required, different than parsing a regular FormData request.

Regards,
Dimiter Madjarov
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Chau
Top achievements
Rank 1
commented on 26 Mar 2019, 07:40 PM

Thanks Dimiter about the rawFile property info.

I got my upload to work as expected.

Here's my sample code if anyone is interested:

On the client side: the uploadEventHandler is passing a Set<File> to the WebAPI controller on the server.

uploadEventHandler(e: UploadEvent) {
this.kendoFiles = e.files;
this.filesSet = new Set<File>();
for (let i = 0; i < this.kendoFiles.length; i++) {
const rawFile: File = this.kendoFiles[i].rawFile;
this.filesSet.add(rawFile);
}
this.fileservice.isLoading = true;

var documentversionid = "123";
this.fileservice.uploadFile(this._filesSet, documentversionid);

}

In fileservice.service.ts: function uploadFile sends a POST request to the WebAPI Controller

uploadFile(filesSet: Set<File>, documentversionid: string) {
filesSet.forEach(file => {
   // create a new multipart-form for every file
   const formdata: FormData = new FormData();
   formdata.append('file', file);
   formdata.append('filetype_for_upload', documentversionid);

// create a http-post request and pass the form
// tell it to report the upload progress
const apiURL = this.api_path + 'Upload';

const uploadReq = new HttpRequest('POST', apiURL, formdata, {
reportProgress: true,
responseType: 'text'
}
);
this.httpclient.request(uploadReq).subscribe(event => {
if (event.type === HttpEventType.UploadProgress) {
this.progress = Math.round(100 * event.loaded / event.total);
}
});
});

}

WebAPI Controller code:

public class UploadController : ApiController
{

       [HttpPost]
        public async Task<HttpResponseMessage> Post()
        {
            try
            {

                 //read file and save to disk

                var uploadpath = ConfigurationManager.AppSettings["upload"];
                DirectoryInfo di = Directory.CreateDirectory(uploadpath);      //physical file path location to save uploaded file

                HttpResponseMessage result = null;
                var httpRequest = HttpContext.Current.Request;

                var documentversionid= httpRequest.Form["documentversionid"];   //get the value passed from client

                //to get file content
                if (httpRequest.Files.Count > 0)
                {
                    var docfiles = new List<string>();
                    foreach (string file in httpRequest.Files)
                    {
                        var postedFile = httpRequest.Files[file];                       
                        var outfilePath = Path.Combine(uploadpath, postedFile.FileName);

                        if (File.Exists(outfilePath))
                            File.Delete(outfilePath);

                        postedFile.SaveAs(outfilePath);
                        docfiles.Add(outfilePath);
                    }
                    result = Request.CreateResponse(HttpStatusCode.Created, docfiles);
                }
                else
                {
                    result = Request.CreateResponse(HttpStatusCode.BadRequest);
                }
                return result;

            }

            catch (Exception ex)
            {
                return Request.CreateResponse<Exception>(HttpStatusCode.InternalServerError, ex);
            }

       }

}

Note: The kendo-upload HTML still needs to have [saveUrl] property defined. (even though  my updateEventHandler function already posted the file request to the WebAPI controller).  Set the saveUrl value to the same url used to make the POST request to WebApi controller (to avoid seeing the error 'Not found' during the file upload), or add code to intercept the redundant second request to  NOT POST to server caused by setting a value in [saveUrl].

<kendo-upload
[autoUpload]="false"
[saveUrl]="uploadSaveUrl"
[restrictions]="uploadRestrictions"
(select)="selectEventHandler($event)"
(clear)="clearEventHandler($event)"
(remove)="removeEventHandler($event)"
(complete)="completeEventHandler($event)"
(upload)="uploadEventHandler($event)" >
</kendo-upload>

Dimiter Topalov
Telerik team
commented on 28 Mar 2019, 09:15 AM

Hi Chau,

We are glad to understand that the provided information proved useful. Thank you for sharing your solution with the community.

Regards,
Dimiter Topalov
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Chau
Top achievements
Rank 1
commented on 29 Mar 2019, 06:57 PM

Hi Dimiter,

I'd like to know if it's possible to customize the kendo-upload component to modify:

a) the area with the upload progress check mark and label 'Done': It looks like currently this is handled (by default) using the saveUrl property, if the  saveUrl POST request is not found, then the upload progress icon is shown with an exclamation.

b) the color of the uploaded file: if the saveUrl property POST request returns an HttpStatus.OK, the color will be green, otherwise red.

In my app, I have an HttpInterceptor to catch the saveUrl and prevent it to send a redundant request to server, so I return a HttpStatus.OK there.

I have custom code in the UploadEventHandler calling WebAPI Controller, which can return an exception due to business logic, and I am looking for ways to set the uploaded file color to red, and also set the upload progress icon to be an exclamation with a label 'Error importing file'.

Dimiter Madjarov
Telerik team
commented on 01 Apr 2019, 07:46 AM

Hi Chau,


Please check my answer in the other thread on the same topic. I think it also covers this question. Let me know if I am missing something here.

For simplicity lets keep the conversation going in one of those threads.

Regards,
Dimiter Madjarov
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
General Discussions
Asked by
yamaha
Top achievements
Rank 1
Answers by
Dimiter Madjarov
Telerik team
Share this question
or