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 2342 posts 14889 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

Please Sign in or register to post replies

Write your reply to:

Draft