[Solved] File Upload
c
Does Umbraco give us any help when uploading files from an input type="file"? I'm happy saving the file once I've got hold of it, but trying to get my head around how to get it off the user's machine. Currently I only seem to get a string which is the file name, no path to stream it from nor file object. I feel I'm missing something somewhere. It's just a .net core Html.BeginForm posting to a Surface Controller.
a
IIRC you can also add a parameter with the right syntax (which I can't remember what it :o)
c
Thanks. It's empty 😦
Copy code
var test = HttpContext.Request.Form.Files;
gives count 0 Now I've changed the model from "string" to "object" I get:-
Copy code
var test = model.SinglePhoto;
which is also empty, whereas it gave the file name when it was a string.
I'm using Html.BeginForm because I can't get Html.BeginUmbracoForm to work.
a
Can you share some more code from your form?
c
Sure, it's a big form so I've just cut out the file upload bits and removed the classes for clarity....
Copy code
@using (Html.BeginForm("Submit", "MemorialFormSurface", FormMethod.Post, new { @id=formId, enqType="multipart/form-data" })) {
    @Html.AntiForgeryToken()

    <div>
        <label asp-for="@Model.SinglePhoto">Please attach a photo of the person on their own.</label>
        <div>
            <input type="file" asp-for="@Model.SinglePhoto" data-val="false" data-val-required="Please select a single file in png, jpg, gif or webp format" accept=".jpg, .png, .gif, .webp">
            <span asp-validation-for="@Model.SinglePhoto" data-valmsg-replace="true"></span>
        </div>
    </div>

    <div>
        <label asp-for="@Model.OtherPhotos">Please attach up to 5 other photos of the person.</label>
        <div>
            <input type="file" asp-for="@Model.OtherPhotos" multiple data-val="false" data-val-required="Please select a single file in png, jpg, gif or webp format" accept=".jpg, .png, .gif, .webp">
            <span asp-validation-for="@Model.OtherPhotos" data-valmsg-replace="true"></span>
        </div>
    </div>        
}
a
How does the rendered HTML look? I'm noticing that both fields doesn't specify a name - but that might be set by the call to
asp-for="@Model.SinglePhoto"
c
The form tag looks like this:-
Copy code
<form action="/umbraco/surface/memorialformsurface/Submit" enqType="multipart/form-data" id="a133e50a-432f-43f5-8fff-393a6985945a" method="post">
and the two file inputs look like this:-
Copy code
<input type="file" data-val="false" data-val-required="Please select a single file in png, jpg, gif or webp format" accept=".jpg, .png, .gif, .webp" id="SinglePhoto" name="SinglePhoto">

<input type="file" multiple data-val="false" data-val-required="Please select a single file in png, jpg, gif or webp format" accept=".jpg, .png, .gif, .webp" id="OtherPhotos" name="OtherPhotos">
If it makes a difference, the form is a Block Grid block partial.
a
Shouldn't matter that it's in a partial
c
Here's the debug :-
No files 😦
If I make SinglePhoto an IFormFile then I get a SaveUploadedFileToTempFolder available which is tempting. But don't know what to put in IHostingEnvironment:-
Copy code
var test = model.SinglePhoto.SaveUploadedFileToTempFolder(IHostingEnvironment);
a
How does your controller look? Changing the type to
IFormFile
sounds correct, but I can't get it to work with my test controller
c
Basically this....
Copy code
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Logging;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Web.Website.Controllers;
using Web.Core.Models;
using Web.Core.Services;

namespace Web.Core.Controllers; 

public class MemorialFormSurfaceController : SurfaceController {
    
    private readonly IUmbracoContextAccessor _umbracoContextAccessor;
    private readonly IContentService _contentService;
    private readonly IMediaService _mediaService;
    private readonly Helpers _helpers;
    private readonly IWebHostEnvironment _environment;


    public MemorialFormSurfaceController(IUmbracoContextAccessor umbracoContextAccessor,
        IUmbracoDatabaseFactory databaseFactory,
        ServiceContext services,
        IContentService contentService,
        IMediaService mediaService,
        AppCaches appCaches,
        IProfilingLogger profilingLogger,
        IPublishedUrlProvider publishedUrlProvider,
        Helpers helpers,
        IWebHostEnvironment environment) : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider) { 
        _umbracoContextAccessor = umbracoContextAccessor;
        _contentService = contentService;
        _mediaService = mediaService;
        _helpers = helpers;
        _environment = environment;
    }
    
    [HttpPost]
    public IActionResult Submit(MemorialFormModel model)
    {
        if (!ModelState.IsValid)
        {
            return CurrentUmbracoPage();
        }

    // All the other stuff......
}
a
Ok. Problem seems that the content type is
appplication/x-www-form-urlencoded
.
Hmm. The problem seems to be that you've written
enqType
(with a q) opposed to
encType
(with a c)
With the correct spelling, it works
c
I hope it's not just that, I'll shoot myself, lol Trying now........
I now have a count of "1" !!!!
So the last thing I need to know on this one is how to differentiate between the two file upload fields. I presume it's just Request.Form["myNewField"].Files? But it isn't 😦
a
My model looks like this:
Copy code
csharp
public class CraigModel {

    public IFormFile? SinglePhoto { get; set; }

    public List<IFormFile>? OtherPhotos { get; set; }

}
So you can read them from your model instead of from the request as I suggested earlier
c
I don't see that, have just read back the thread, Ah, I showed you it earlier, maybe it works now, after the typo correction. ``var test = model.SinglePhoto;``
It does! It never stops amazing me how you can set of with the tiniest error and go off an a round the world tour and come back to almost where you started. Thank you so much for your time, it is really appreciated. Even more so on a weekend! 🙂
a
It's a rainy day, so just sitting inside watching some cycling and dabbling with some code :p
66 Views