0

I need to upload an image (single) to the server using Ajax. Action will call the post Method on my API controller.

Up to this point, I found only outdated and broken solution like this :

https://www.c-sharpcorner.com/UploadFile/manas1/upload-files-through-jquery-ajax-in-Asp-Net-mvc/

or this : Uploading File using Ajax in Asp.Net Core

Also, it was surprising that example from Microsoft documentation not working either in my case, https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-2.1#match-name-attribute-value-to-parameter-name-of-post-method

List<IFormFile> files was null, I don't know why.

My Current code :

HTML

<form id="InputBannerForm"  action="@Url.Action("UploadLocalBanner", "Api")" enctype="multipart/form-data" onsubmit="AJAXSubmit(this);return false;" method="post" >
                            <div class="row justify-content-center">
                                <div class="col-12 col-md-6 mb-3">
                            <div>
                            <label for="InputBanner" class="col-12"  >@Localizer["banner"]</label>
                            <input id="InputBanner" type="file" accept="image/jpeg, image/png" onchange="onInputBannerChange()">
                      </div>
                </div>
           </div>
    </form>

JS :

function onInputBannerChange() {
    document.getElementById("InputBannerForm").submit();
}

async function AJAXSubmit(oFormElement) {
    var resultElement = oFormElement.elements.namedItem("result");
    const formData = new FormData(oFormElement);

    try {
        const response = await fetch(oFormElement.action, {
            method: 'POST',
            body: formData
        });

        if (response.ok) { console.log("succes"); }

        resultElement.value = 'Result: ' + response.status + ' ' +
            response.statusText;
    } catch (error) {
        console.error('Error:', error);
    }
}

Controller :

[Route("SO-{clientId}/{controller}/{action}")]
[HttpPost]
public async Task<IActionResult> UploadLocalBanner(IList<IFormFile> files)
{
    try
    {
        IFormFile source = files[0];
        string filename = System.Net.Http.Headers.ContentDispositionHeaderValue.Parse(source.ContentDisposition).FileName.Trim('"');

        if (filename.Contains("\\"))
            filename = filename.Substring(filename.LastIndexOf("\\") + 1);

        string relativePath = "wwwroot\\Images\\LocalBanners";

        string targetDirectory = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), relativePath);
        if (!System.IO.Directory.Exists(targetDirectory))
            System.IO.Directory.CreateDirectory(targetDirectory);

        using (System.IO.FileStream output = System.IO.File.Create(System.IO.Path.Combine(targetDirectory, filename)))
        {
            await source.CopyToAsync(output);
        }
    
        return Ok();
    }
    catch(Exception ex)
    {
        return BadRequest(ex);
    }
}
4
  • Have you tried the [FromForm] parameter attribute - UploadLocalBanner([FromForm]IList<IFormFile> files) Commented Jun 30, 2022 at 9:52
  • Yes, I was trying this. i also was trying List<IFormFile> [FromForm]List<IFormFile> IFormFile [FromForm]IFormFile Commented Jun 30, 2022 at 9:55
  • Can my answer help you? Commented Jun 30, 2022 at 10:02
  • When was I trying to use your approach I have error in my small script for __RequestVerificationToken if (window.jQuery) { $.ajaxPrefilter(function (options, originalOptions, xhr) {... here error .... } ); } error is : Uncaught TypeError: options.data.indexOf is not a function Commented Jun 30, 2022 at 10:11

1 Answer 1

0

I manage to achieve my goal with this code :

    <div id="TableHeader" class="row header">
        <h3 >@Localizer["_Local Banners List_ : "]</h3>
        <input type="file" id="imageUploadForm"  name="image" multiple="multiple" />
    </div>

This is my Ajax request :

$(document).ready(function() {
    $("#imageUploadForm").change(function() {
        var formData = new FormData();
        var totalFiles = document.getElementById("imageUploadForm").files.length;
        for (var i = 0; i < totalFiles; i++) {
            var file = document.getElementById("imageUploadForm").files[i];
            formData.append("imageUploadForm", file);
        }
        formData.append("localId", @Model.LocalId);

        $.ajax({
            type: "POST",
            url: _UploadLocalBannerImage,
            data: formData,
            dataType: 'json',
            contentType: false,
            processData: false
        }).done(function() { alert('success'); }).fail(function(xhr, status, errorThrown) { alert('fail'); });
    });
});

And this is how I handle request on server :

    [HttpPost]
    public IActionResult UploadasdaLocalBannerImage(int localId)
    {

        if (Request.Form.Files.Count != 0)
        {
            for (int i = 0; i < Request.Form.Files.Count; i++)
            {
                var file = Request.Form.Files[i];
                // var fileName = System.IO.Path.GetFileName(file.FileName);

                // some logic before aploading file and prepearing
                
                string absolutePath = System.IO.Path.Combine(Environment.CurrentDirectory, "path to file");
                using (var stream = new System.IO.FileStream(absolutePath, System.IO.FileMode.Create))
                {
                    file.CopyTo(stream);
                }

                // some logic after file uploaded

                return Ok();
                //file.SaveAs(path);
            }

        }
        return BadRequest();

    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.