Отправить форму, используя AJAX в ASP.Net Core MVC

Я работаю с ASP.Net Core 2.1 и пытаюсь загрузить файл, возвращая его URL-адрес, не обновляя страницу.

Я пытаюсь написать JavaScript в site.js, так как _RenderPartial("scripts") отображает все сценарии в конце страницы и, следовательно, непосредственное использование тега script в представлении бритвы не работает. Во-вторых, добавление его в site.js дает мне возможность вызывать скрипт для всех видов сайта.

Мое действие контроллера выглядит так:

    [HttpPost]
    [DisableRequestSizeLimit]
    public async Task<IActionResult> Upload()
    {
      // Read & copy to stream the content of MultiPart-Form
      // Return the URL of the uploaded file
      return Content(FileName);
    }

Мой взгляд выглядит так:

<form id="FileUploadForm" action="~/Resources/Upload" method="post" enctype="multipart/form-data">
<input name="uploadfile" type="file" />
<button name="uploadbtn" type="submit" onclick="SubmitForm(this.parentElement, event)">Upload</button>

В настоящее время site.js выглядит так:

function SubmitForm(form, caller) {
caller.preventDefault();
$.ajax(
    {
        type: form.method,
        url: form.action,
        data: form.serialize(),
        success: function (data) { alert(data); },
        error: function (data) { alert(data); }
    })}

В настоящее время код обходит весь сценарий, и файл загружается, и возвращается новое представление, отображающее имя файла. Мне нужна помощь для создания JavaScript.

3 ответа

Решение

К сожалению, JQuery serialize() Метод не будет включать элементы входного файла. Таким образом, выбранный пользователем файл не будет включен в сериализованное значение (которое в основном является строкой).

Что вы можете сделать, это создать FormData объект, добавьте файл (ы) к этому. При выполнении вызова AJAX необходимо указать processData а также contentType значения свойств для false

<form id="FileUploadForm" asp-action="Upload" asp-controller="Home" 
                                              method="post" enctype="multipart/form-data">
    <input id="uploadfile" type="file" />
    <button name="uploadbtn" type="submit">Upload</button>
</form>

и здесь ненавязчивым способом обрабатывается событие отправки формы, где мы остановим обычное поведение и вместо этого сделаем отправку ajax.

$(function () {
    $("#FileUploadForm").submit(function (e) {
        e.preventDefault();

        console.log('Doing ajax submit');

        var formAction = $(this).attr("action");
        var fdata = new FormData();

        var fileInput = $('#uploadfile')[0];
        var file = fileInput.files[0];
        fdata.append("file", file);

        $.ajax({
            type: 'post',
            url: formAction,
            data: fdata,
            processData: false,
            contentType: false
        }).done(function (result) {
            // do something with the result now
            console.log(result);
            if (result.status === "success") {
                alert(result.url);
            } else {
                alert(result.message);
            }
        });
    });
})

Предполагая, что у вашего метода на стороне сервера есть параметр с именем, совпадающим с тем, который мы использовали при создании FormData запись объекта (file). Вот пример, где он будет загружать изображение в uploads каталог внутри wwwwroot,

Метод action возвращает объект JSON со свойством status и url/message, и вы можете использовать его в success/done обработчик вызова AJAX на все, что вы хотите сделать.

public class HomeController : Controller
{
    private readonly IHostingEnvironment hostingEnvironment;
    public HomeController(IHostingEnvironment environment)
    {
        _context = context;
        hostingEnvironment = environment;
    }
    [HttpPost]
    public async Task<IActionResult> Upload(IFormFile file)
    {
        try
        {
            var uniqueFileName = GetUniqueFileName(file.FileName);
            var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
            var filePath = Path.Combine(uploads, uniqueFileName);
            file.CopyTo(new FileStream(filePath, FileMode.Create));
            var url = Url.Content("~/uploads/" + uniqueFileName);
            return Json(new { status = "success", url = url });
        }
        catch(Exception ex)
        {
            // to do : log error
            return Json(new { status = "error", message = ex.Message });
        }
    }
    private string GetUniqueFileName(string fileName)
    {
        fileName = Path.GetFileName(fileName);
        return Path.GetFileNameWithoutExtension(fileName)
                  + "_"
                  + Guid.NewGuid().ToString().Substring(0, 4)
                  + Path.GetExtension(fileName);
    }
}

Поделиться кодом, который работал для меня, реализуя ответ @Shyju.

Вид (Страница Razor):

<form name="UploadForm" action="~/Resources/Upload" method="post" enctype="multipart/form-data">
<input name="uploadfile" type="file" />
<button name="uploadbtn" type="submit" onclick="SubmitForm(this.parentElement, event)">Upload</button>

Код AJAX, добавленный в Site.js (чтобы сделать его многоразовым):

// The function takes Form and the event object as parameter
function SubmitForm(frm, caller) {
caller.preventDefault();

var fdata = new FormData();

var file = $(frm).find('input:file[name="uploadfile"]')[0].files[0];
fdata.append("file", file);

$.ajax(
    {
        type: frm.method,
        url: frm.action,
        data: fdata, 
        processData: false,
        contentType: false,
        success: function (data) {
            alert(data);
        },
        error: function (data) {
            alert(data);
        }
    })

};

если вы хотите отправить форму без использования запроса ajax

      var form = document.getElementById('formId');

form.submit();
Другие вопросы по тегам