Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Neil Hodges 338 posts 987 karma points
    Mar 18, 2021 @ 16:48
    Neil Hodges
    0

    Umbraco 8 Backoffice - Upload a file - Angular

    Hi

    So I have some code that worked perfectly in Umbraco v7, but I guess something has changed with regards to Angular and Umbraco 8.

    I've created a custom Dashboard in the back office and I'm in need of uploading an Excel Spreadsheet to my Controller.

    I have the following View in the Dashboard:

    <div ng-controller="UploadController">
        <umb-box>
            <umb-box-header title="Upload Postcodes"></umb-box-header>
            <div class="flex justify-start">
                <umb-box-content>
                    <p>
                        Below please select an Excel spreadsheet that contains a list of postcodes for the site.
                        <br />The Excel format should be in the same format as the example image here >
                    </p>
    
                    <div class="flex content-start">
                        <div class="ng-scope">
                            <div class="umb-el-wrap">
                                <div ng-show="errorMsg && errorMsg != ''" class="alert alert-error property-error ng-binding" style="display: none;">{{errorMsg}}</div>
                                <div ng-show="statusMsg && statusMsg != ''" class="alert alert-info property-error ng-binding" style="display: none;">{{statusMsg}}</div>
    
                                <ng-form id="clinicAddForm" name="clinicAddForm" class="ng-pristine ng-valid ng-valid-required" val-form-manager>
                                    <label for="postcodesAdd.postCodeUploadInput" style="display: inherit"><strong>Excel Spreadsheet Upload:</strong></label>
                                    <br />
                                    <input type="file" id="postcodesAdd.postCodeUploadInput" name="file" onchange="angular.element(this).scope().LoadFileData(this.files)" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" />
    
                                    <button label="Upload" ng-click="addPostcodes(postcodesAdd)" class="primary">
                                        Upload
                                    </button>
                                </ng-form>
                            </div>
                        </div>
    
                    </div>
    
    
                </umb-box-content>
                <umb-box-content>
                    <img src="../../../../images/excel-data-example.jpg" />
                </umb-box-content>
            </div>
    
        </umb-box>
    </div>
    

    JS Controller:

    function UploadController($scope,$http) {
        $scope.post = "/umbraco/Surface/PostCodeLookUpSurface/UploadPostcodes";
    
        $scope.errorMsg = "";
        $scope.statusMsg = "";
    
        $scope.files = [];
    
        $scope.LoadFileData = function (files) {
            $scope.files = files;
        };
    
        $scope.addPostcodes = function () {
            $http({
                url: $scope.post,
                method: "POST",
                headers: { "Content-Type": undefined },
                transformRequest: function (data) {
                    var formData = new FormData();
    
                    for (var i = 0; i < data.files.length; i++) {
                        formData.append("files[" + i + "]", data.files[i]);
                    }
    
                    return formData;
                },
                data: { files: $scope.files }
            }).then(function (response) {
    
            });
    
        };
    
    }
    
    angular.module("umbraco").controller("uploadController", UploadController);
    

    Surface Controller:

     [System.Web.Http.HttpPost]
            public ActionResult UploadPostcodes(HttpPostedFileBase[] files)
            {
                return null;
            }
    

    Now when i select the files to upload, im getting a console error that LoadFileData is undefined?

    enter image description here

    Any pointers on why its undefined, i declare it in $scope.LoadFileData Or if someone has a better approach to uploading a file to a Controller?

  • Kevin Jump 2348 posts 14896 karma points MVP 8x c-trib
    Mar 18, 2021 @ 17:12
    Kevin Jump
    2

    Hi,

    I have some sample code for uploading files in v8
    https://github.com/KevinJump/DoStuffWithUmbraco/tree/master/Src/DoStuff.Core/FileUpload

    this might help.

  • Matthew Wise 271 posts 1373 karma points MVP 5x c-trib
    Mar 18, 2021 @ 17:14
    Matthew Wise
    0

    Used this the yesterday :) most helpful as always @Kevin

  • Neil Hodges 338 posts 987 karma points
    Mar 19, 2021 @ 11:26
    Neil Hodges
    1

    Hi Kevin

    Thanks for this, I'm just trying to follow along with the code, think I've nearly got it, but can't seem to hit the controller with a breakpoint to see the file being uploaded.

    I'm going to at that point extract data from the excel sheet and input it into a table.

    Here is what I have so far, but it never gets to the Controller - UploadFile()

    upload.controller.js

    angular.module("umbraco").controller("uploadController", function ($http) {
        var vm = this;
    
        function handleFiles(files, event) {
            if (files && files.length > 0) {
                vm.file = files[0];
            }
        }
    
        function upload(file) {
            vm.buttonState = 'busy';
            Upload.upload({
                url: Umbraco.Sys.ServerVariables.doStuffFileUpload.uploadService + 'UploadFile',
                fields: {
                    'someId': 1234
                },
                file: file
            }).success(function (data, status, headers, config) {
                vm.buttonState = 'success';
                notificationsService.success('Uploaded', data);
            }).error(function (data, status, headers, config) {
                vm.buttonState = 'error';
                notificationsService.error('Upload Failed', data);
            });
        }
    
    });
    

    upload.html

    <div>
        <umb-box>
            <umb-box-header title="Upload Postcodes"></umb-box-header>
            <div class="flex justify-start">
                <umb-box-content>
                    <p>
                        Below please select an Excel spread sheet that contains a list of postcodes for the site.
                        <br />The Excel format should be in the same format as the example image here >
                    </p>
    
                    <div class="flex content-start">
                        <div class="ng-scope">
                            <div class="umb-el-wrap" ng-controller="uploadController as vm">
                                <div ng-show="errorMsg && errorMsg != ''" class="alert alert-error property-error ng-binding" style="display: none;">{{errorMsg}}</div>
                                <div ng-show="statusMsg && statusMsg != ''" class="alert alert-info property-error ng-binding" style="display: none;">{{statusMsg}}</div>
    
    
                                <input id="dostufffilepicker"
                                       type="file"
                                       accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
                                       ngf-select
                                       ngf-model="filesHolder"
                                       ngf-change="vm.handleFiles($files, $event)"
                                       ngf-multipart="true" />
    
                                <!--<label for="dostufffilepicker"
                                       class="btn btn-default">Choose File</label>
                                <br/>
                                <br/>-->
                                <umb-button action="vm.upload(vm.file)"
                                            type="button"
                                            label-key="postcodeButtons_general_upload"
                                            button-style="success"
                                            state="vm.buttonState"
                                            disabled="vm.buttonState == 'busy'">
                                </umb-button>
    
                            </div>
                        </div>
    
                    </div>
    
    
                </umb-box-content>
                <umb-box-content>
                    <img src="../../../../images/excel-data-example.jpg" />
    
                </umb-box-content>
            </div>
    
        </umb-box>
    </div>
    

    DoStuffUploadApiController.js

     public class DoStuffUploadApiController : UmbracoAuthorizedApiController
        {
            /// <summary>
            ///  simple call, used to locate the controller
            ///  when we inject it into the javascript varibles.
            /// </summary>
            /// <returns></returns>
            [HttpGet]
            public string GetApi() => "Hello";
    
            /// <summary>
            ///  upload a file to a folder in app_data
            /// </summary>
            /// <returns>name of the file</returns>
            [HttpPost]
            public async Task<string> UploadFile()
            {
                if (!Request.Content.IsMimeMultipartContent())
                    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    
                var uploadFolder = IOHelper.MapPath("~/App_Data/Temp/DoStuffUploads/");
                Directory.CreateDirectory(uploadFolder);
    
                var provider = new CustomMultipartFormDataStreamProvider(uploadFolder);
                var result = await Request.Content.ReadAsMultipartAsync(provider);
                var filename = result.FileData.First().LocalFileName;
    
                var someId = result.FormData["someId"];
    
                if (filename == null)
                    throw new HttpResponseException(HttpStatusCode.NoContent);
    
                // at this point filename points to the local file uploaded into the folder
                // you can manipulate it at will :)
    
                return Path.GetFileNameWithoutExtension(filename);
            }
    
            /// <summary>
            ///  by using a custom multipart provider we can also send form data with the file
            ///  which is useful when you have other things to say too. 
            /// </summary>
    
            public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
            {
                public CustomMultipartFormDataStreamProvider(string path) : base(path) { }
    
                public override string GetLocalFileName(HttpContentHeaders headers)
                {
                    return headers.ContentDisposition.FileName.Replace("\"", string.Empty);
                }
            }
        }
    

    and finally FileUploadComposer.cs

     public class FileUploadComposer : ComponentComposer<FileUploadComponent>
        { }
    
        public class FileUploadComponent : IComponent
        {
            public void Initialize()
            {
                ServerVariablesParser.Parsing += ServerVariablesParser_Parsing;
            }
    
            /// <summary>
            ///  called at startup when the javascript server variables are being
            ///  built.
            /// </summary>
            private void ServerVariablesParser_Parsing(object sender, Dictionary<string, object> e)
            {
                if (HttpContext.Current == null)
                    throw new InvalidOperationException("This method requires that an HttpContext be active");
    
                var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()));
    
                e.Add("doStuffFileUpload", new Dictionary<string, object>
                {
                    { "uploadService", urlHelper.GetUmbracoApiServiceBaseUrl<DoStuffUploadApiController>(controller => controller.GetApi()) }
                });
    
            }
    
            public void Terminate()
            {
                // closing down
            }
        }
    

    I assume is it the upload.controller.js where I'm going wrong with it here?

  • Neil Hodges 338 posts 987 karma points
    Mar 19, 2021 @ 11:57
    Neil Hodges
    1

    Ok, reading the code base a little more in depth i can see where ive gone wrong now.

    Altered controller code to:

    angular.module("umbraco").controller("uploadController", function ($scope, $http, notificationsService, Upload) {
        var vm = this;
        vm.buttonState = 'init';
    
    
    
        vm.handleFiles = handleFiles;
        vm.upload = upload;
    
        function handleFiles(files, event) {
            if (files && files.length > 0) {
                console.log("hit files");
                vm.file = files[0];
            }
        }
    
        function upload(file) {
            console.log("hit upload");
    
            vm.buttonState = 'busy';
            Upload.upload({
                url: Umbraco.Sys.ServerVariables.doStuffFileUpload.uploadService + 'UploadFile',
                fields: {
                    'someId': 1234
                },
                file: file
            }).success(function (data, status, headers, config) {
                vm.buttonState = 'success';
                notificationsService.success('Uploaded', data);
            }).error(function (data, status, headers, config) {
                vm.buttonState = 'error';
                notificationsService.error('Upload Failed', data);
            });
        }
    
    
    
    });
    

    Seems to work fine now,

    Cheers, Kevin #H5YR!!

  • Jonathon Cove 26 posts 101 karma points
    Sep 22, 2023 @ 10:07
    Jonathon Cove
    0

    If anyone finds this thread and is working with v9+ (like I did) , there is a good answer here https://our.umbraco.com/forum/using-umbraco-and-getting-started/110844-uploading-files-via-angularjs-in-backoffice#comment-343036

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies