by Vesselin Vassilev
Last Updated On Jul 29, 2017
In general, you need to configure save action that will receive the uploaded files. An optional remove action is also available. Let's see how this can be done in Sitefinity.
Goal
Create a front-end widget that will allow a logged in user to upload one or more files asynchronously to a Sitefinity Document Library.
Implementation
I'll use Sitefinity Feather to create an ASP.NET MVC widget.
Controller
The main controller itself will be very simple - it will just register the widget to the Page Toolbox (via the ControllerToolboxItem attribute) and return the View where the client side code will reside.
using System.Web.Mvc;using Telerik.Sitefinity.Mvc;namespace SitefinityWebApp.Mvc.Controllers{ [ControllerToolboxItem(Name = "FileAsyncUploader", Title = "File Async Uploader", SectionName = "Custom MVC", CssClass = "sfMvcIcn")] public class FileAsyncUploaderController: Controller { [HttpGet] public ActionResult Index() { return View("Index"); } [HttpPost] public ActionResult Upload() { // save the file to Sitefinity return new EmptyResult(); } }}

using System;using System.Linq;using System.Web.Hosting;using System.Web.Http;using System.Web.Optimization;using System.Web.Routing;using Telerik.Sitefinity.Services;namespace SitefinityWebApp{ public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { SystemManager.ApplicationStart += SystemManager_ApplicationStart; } private void SystemManager_ApplicationStart(object sender, EventArgs e) { RegisterRoutes(RouteTable.Routes); } private void RegisterRoutes(RouteCollection routes) { routes.MapHttpRoute( name: "MyCustomApi", routeTemplate: "ajax/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } }}using System;using System.Net;using System.Net.Http;using System.Web.Http;using Telerik.Sitefinity.Abstractions;using System.Linq;using System.Collections.Generic;using System.Web;using System.IO;using Telerik.Sitefinity.Libraries.Model;using Telerik.Sitefinity.Modules.Libraries;using Telerik.Sitefinity.Workflow;using Telerik.Sitefinity.Data;using System.Text.RegularExpressions;using Telerik.Sitefinity.Security.Claims;using Telerik.Sitefinity.GenericContent.Model;namespace SitefinityWebApp.Mvc.Api{ public class FilesController : ApiController { [HttpPost] public HttpResponseMessage Upload() { var user = ClaimsManager.GetCurrentIdentity(); if (!user.IsAuthenticated) { return Request.CreateErrorResponse(HttpStatusCode.Forbidden, "You must be authenticated to upload files"); } var error = string.Empty; var files = HttpContext.Current.Request.Files; if (files != null) { var manager = LibrariesManager.GetManager(); using (var reg = new ElevatedModeRegion(manager)) { // create a library with the name of the logged in user var libTitle = user.Name; var library = GetOrCreateDocumentsLibrary(libTitle); for (int i = 0; i < files.Count; i++) { var file = files[i]; try { // Some browsers send file names with full path. // This needs to be stripped. var fileName = Path.GetFileName(file.FileName); var ext = Path.GetExtension(file.FileName).ToLower(); var docId = Guid.NewGuid(); var doc = manager.CreateDocument(docId); var utcNow = DateTime.UtcNow; doc.Parent = library; doc.Title = fileName; doc.DateCreated = utcNow; doc.PublicationDate = utcNow; doc.LastModified = utcNow; var urlName = CreateSitefinityUrlFromString(fileName); doc.UrlName = doc.MediaFileUrlName = urlName; manager.Upload(doc, file.InputStream, ext); manager.RecompileItemUrls(doc); manager.SaveChanges(); var bag = new Dictionary<string, string>(); bag.Add("ContentType", typeof(Document).FullName); WorkflowManager.MessageWorkflow(docId, typeof(Document), null, "Publish", false, bag); } catch (Exception ex) { Log.Write(ex.ToString()); error = "Failed to upload: " + file.FileName + ex.ToString(); } } } } // Return an empty string to signify success or an error message otherwise return Request.CreateResponse(HttpStatusCode.OK, error); } [HttpPost] public HttpResponseMessage Remove([FromBody] RemoveFileModel filesToRemove) { var user = ClaimsManager.GetCurrentIdentity(); if (!user.IsAuthenticated) { return Request.CreateErrorResponse(HttpStatusCode.Forbidden, "You must be authenticated to upload files"); } var manager = LibrariesManager.GetManager(); using (var region = new ElevatedModeRegion(manager)) { var library = manager.GetDocumentLibraries() .Where(l => l.Title == user.Name) .Single(); var fileNames = filesToRemove.fileNames; var docToDelete = library.Documents() .Where(d => d.Status == ContentLifecycleStatus.Master) .Where(d => fileNames.Contains(d.Title.ToString())) .ToList(); docToDelete.ForEach(d => manager.DeleteDocument(d)); manager.SaveChanges(); } return Request.CreateResponse(HttpStatusCode.OK); } public Library GetOrCreateDocumentsLibrary(string title) { var librariesManager = LibrariesManager.GetManager(); Library library = null; using (var region = new ElevatedModeRegion(librariesManager)) { var libs = librariesManager.GetDocumentLibraries().Where(l => l.Title == title); if (libs.Count() == 0) { library = librariesManager.CreateDocumentLibrary(); library.Title = title; library.DateCreated = DateTime.UtcNow; library.LastModified = DateTime.UtcNow; library.UrlName = CreateSitefinityUrlFromString(title); librariesManager.RecompileAndValidateUrls(library); librariesManager.SaveChanges(); } else { library = libs.First(); } } return library; } public string CreateSitefinityUrlFromString(string title, bool isTitleNotUnique = false) { var url = Regex.Replace(title.ToLower(), @"[^\w\-\!\$\'\(\)\=\@\d_]+", "-"); if (isTitleNotUnique) { url += Guid.NewGuid().ToString(); } return url; } } public class RemoveFileModel { // the name of the files to be deleted public string[] fileNames { get; set; } }}
@using Telerik.Sitefinity.Frontend.Mvc.Helpers;@using Telerik.Sitefinity.Modules.Pages;@Html.Script(ScriptRef.KendoWeb, "bottom")@Html.StyleSheet("//kendo.cdn.telerik.com/2017.2.504/styles/kendo.common-bootstrap.min.css", "head")@Html.StyleSheet("//kendo.cdn.telerik.com/2017.2.504/styles/kendo.bootstrap.min.css", "head")<div class="row"> <div class="col-md-4"> <div class="form-group"> <label>Upload Files</label> <input name="files" id="files" type="file" /> </div> </div></div><script> $(function() { var saveUrl = '/ajax/files/upload'; var removeUrl = '/ajax/files/remove'; $("#files").kendoUpload({ multiple: true, async: { saveUrl: saveUrl, removeUrl: removeUrl, autoUpload: true, batch: true } }); })</script>