Copied to clipboard

Flag this post as spam?

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


  • Carlos Casalicchio 169 posts 698 karma points
    Jan 06, 2023 @ 21:49
    Carlos Casalicchio
    0

    Uploading files via angularJs in Backoffice

    I'm trying to upload files via angularJs in the backoffice, and have already tried the UmbracoAuthorizedApiController, UmbracoApiController, and even the SurfaceController (to make sure I'm not going crazy).

    The C# Controller has this method:

    [HttpPost, DisableRequestSizeLimit]
    public async Task<ActionResult> UploadFile([FromForm] IFormFile data)
    {
        if (data == null)
            return BadRequest();
    
        try
        {
            await _extensions.UploadFileAsync(data);
            return Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error Uploading file");
            return BadRequest();
        }
    }
    

    and the angular controller is performing this

    async function uploadFiles() {
        vm.loading = true;
        let files = document.getElementById('file_upload').files;
        if (files.length == 0) {
            notificationsService.warning('Please first choose or drop any file(s)...');
            vm.loading = false;
            return;
        }
        for (let i = 0; i < files.length; i++) {
            let formData = new FormData();
            formData.append('file', files[i]);
            resources.postFile(formData)
                .then(success => {
                if (success) {
                    vm.filesUploaded ??= [];
                    notificationsService.success(`file ${files[i].name} uploaded successfully`);
                    vm.filesUploaded.push(files[i].name);
                }
    
            }, failure => {
                notificationsService.error(`Could not upload: ${failure.data.Title}`)
                console.log(failure);
            });
        }
        vm.loading = false;
    }
    

    and the angularJs resource file has this post

    function postFile(formData) {
        return $http({
            method: 'POST',
            url: `${baseApiUrl}UploadFile`,
            data: formData
        })
    }
    

    And yet, it keeps submitting null files. I attempted several different tutorials online, but nothing works. I'm sure it's something trivial, maybe someone can see it and point me in the right direction, please?

    enter image description here enter image description here

  • Huw Reddick 1702 posts 5999 karma points MVP c-trib
    Jan 07, 2023 @ 09:15
    Huw Reddick
    0

    If you define your action as UploadFile(object data) does data then have a value of Object rather than null? If so then it is probably the data mapping that is incorrect resulting in data being null as data is not an IFormFile

    Have you tried IFormFileCollection instead of IFormFile or even just IFormCollection? Form posts are normally a collection even if it is only one file

  • Carlos Casalicchio 169 posts 698 karma points
    Jan 07, 2023 @ 16:00
    Carlos Casalicchio
    0

    Thanks Huw,

    Yes, it does return an Object. and IFormFileCollection returns an empty list enter image description here

    and so does IFormCollection enter image description here

    I agree that I'm probably mapping the model with the wrong type, but what type should be used, then? Every example and tutorial I've found uses IFormFile (comes null), or even IList<IFormFile> (comes empty) and those are not working.

    What am I missing?

  • Huw Reddick 1702 posts 5999 karma points MVP c-trib
    Jan 07, 2023 @ 16:06
    Huw Reddick
    0

    I've never done it myself so not sure what else to suggest. If I have time later I'll have a twiddle and see if I can work it out, if nobody else comes up with an answer

  • Huw Reddick 1702 posts 5999 karma points MVP c-trib
    Jan 07, 2023 @ 21:42
    Huw Reddick
    101

    I cam across this posted by Kevin, although it is for version 8, I believe it is still valid in 9+

    https://github.com/KevinJump/DoStuffWithUmbraco/tree/master/Src/DoStuff.Core/FileUpload

  • Carlos Casalicchio 169 posts 698 karma points
    Jan 08, 2023 @ 03:35
    Carlos Casalicchio
    0

    Thank you Huw,

    I got it to work like this..

    angularjs controller

        angular.module('umbraco').controller('Umbraco.Plugins.ImportJsonController', function (resources, notificationsService, Upload) {
        const vm = this;
        vm.filesUploaded = null
        const baseAuthApiUrl = "/umbraco/backoffice/api/ImportAuthorizedApi/";
    
        function handleFiles(files, event) {
                vm.file = files;
        }
        function upload() {
            let files = document.getElementById('file_upload').files;
            if (files.length == 0) {
                notificationsService.warning('Please first choose or drop any file(s)...');
                return;
            }
            vm.buttonState = 'busy';
            for (let file of vm.file) {
                Upload.upload({
                    url: baseAuthApiUrl + 'UploadFile',
                    file: file
                }).success(function (data, status, headers, config) {
                    vm.buttonState = 'success';
                    vm.filesUploaded ??= [];
                    vm.filesUploaded.push(file.name);
                    notificationsService.success(`${file.name} uploaded successfully`, data);
                }).error(function (data, status, headers, config) {
                    vm.buttonState = 'error';
                    notificationsService.error(`${file.name} uploaded failed`, data);
                });
            }
        }
    
        vm.upload = upload;
        vm.handleFiles = handleFiles;
    });
    

    view.html

    <div class="main-content">
                <div class="upload-container">
                    <input id="file_upload"
                           type="file"
                           accept=""
                           ngf-select
                           ngf-model="filesHolder"
                           ngf-change="vm.handleFiles($files, $event)"
                           ngf-multipart="true" multiple />
                </div>
    
                <div class="align-right mt-3">
                    <umb-button action="vm.upload()"
                                type="button"
                                label-key="general_upload"
                                button-style="success"
                                ng-if="vm.file != null"
                                state="vm.buttonState"
                                disabled="vm.buttonState == 'busy'">
                    </umb-button>
                </div>
                <div ng-if="vm.filesUploaded">
                    <h5>Files Uploaded</h5>
                    <ul class="list-group">
                        <li ng-repeat="f in vm.filesUploaded" class="list-group-item">{{f}}</li>
                    </ul>
                </div>
            </div>
    

    ImportAuthorizedApiController C#

    [HttpPost, DisableRequestSizeLimit]
    public async Task<ActionResult> UploadFile()
    {
        var request = HttpContext.Request;
        try
        {
            foreach (var file in request.Form.Files)
                await _extensions.UploadFileAsync(file);
    
            return Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error Uploading file");
            return BadRequest();
        }
    }
    

    Also had to update the maxAllowedContentLength to allow large files inside applicationhost.config (or web.config)

      <requestFiltering>
        <requestLimits maxAllowedContentLength="2147483647" />
      </requestFiltering>
    

    It turns out that I needed to set a local variable for Request.Form.Files

    Thank you for your help

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

    Can I ask what class _extensions is ?

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

    I don't think so, as v8 uses .NET Framework, and 9 uses .NET Core, some code in the Controller that receives the file.

    Carlos' answer below is correct

  • Andrew Bright 84 posts 244 karma points
    Apr 09, 2023 @ 13:42
    Andrew Bright
    0

    I am trying to do the same thing in Umbraco 10 but rather than having a separate back office section I am looking to override the existing media upload process essentially bypassing the upload process with a form: loading prompt

    enter image description here

    I have implemented this on v7 and looking to port onto v10 but the angular script isn't even getting hit am I missing a step.

  • Carlos Casalicchio 169 posts 698 karma points
    Apr 10, 2023 @ 15:06
    Carlos Casalicchio
    0

    Hi Andrew,

    Have you tried the notification service?

    https://docs.umbraco.com/umbraco-cms/reference/notifications/mediaservice-notifications

    I'm not sure how else you'd be able to tap into the existing controls.

  • Andrew Bright 84 posts 244 karma points
    Apr 10, 2023 @ 19:05
    Andrew Bright
    0

    Will have a look but was looking to use HTTP interceptor which presented the user with the modal shown above and then pass additional info into the media fields based on their selection.

  • Andrew Bright 84 posts 244 karma points
    Apr 10, 2023 @ 23:18
    Andrew Bright
    0

    Okay new idea could I create an angular form within the interceptor that reads the user values as well as the file details then pass this to the notification handler to do the rest?

Please Sign in or register to post replies

Write your reply to:

Draft