Muitos programadores iniciantes do C # ASP .NET MVC (a seguir denominados mvc) enfrentam a tarefa de enviar dados usando o Ajax. Mas, na prática, essa tarefa não é tão fácil.
No meu trabalho, tento seguir certos princípios de desenvolvimento de software. Uma delas é minimizar a escrita de código e a criação de classes e funções universais. Foi esse princípio que sugeriu o uso de
jquery.unobtrusive-ajax.js e a classe Ajax para
mvc .
Neste artigo, estamos diretamente interessados no Ajax.BeginForm.
Um exemplo:
@using (Ajax.BeginForm("UploadAvatarImage", "Dashboard", null, new AjaxOptions {HttpMethod = "POST", OnSuccess = "UpdateAvatars()", OnFailure = "document.refresh()" }, new {Id = "UploadAvatartForm", enctype = "multipart/form-data" })) { <div class="input-group pt-1 pl-1"> <input type="file" name="avatarFile" class="form-control" id="fileUploaderControl" accept=".jpg"/> </div> <button class="btn btn-sm btn-primary btn-block m-1" type="submit" ></button> }
Diante do fato de que o Ajax.BeginForm não passa pela entrada [type = file], realizei uma pesquisa global para encontrar uma solução para esse problema. O antigo fluxo de
pilha favorito em cada solução oferecia a mesma coisa. Não use Ajax.BeginForm, use FormData, crie um manipulador de php e ainda mais nuvens de dicas para aumentar o código do programa.
Como eu disse anteriormente, em meus produtos eu aderi aos princípios e, como a resposta que satisfaria meus requisitos não foi encontrada, eu tive que fazer tudo sozinha.
A primeira coisa necessária foi determinar qual função no
jquery.unobtrusive-ajax.js é responsável pela geração de dados.
$(document).on("submit", "form[data-ajax=true]", function (evt) { var clickInfo = $(this).data(data_click) || [], clickTarget = $(this).data(data_target), isCancel = clickTarget && (clickTarget.hasClass("cancel") || clickTarget.attr('formnovalidate') !== undefined); evt.preventDefault(); if (!isCancel && !validate(this)) { return; } asyncRequest(this, { url: this.action, type: this.method || "GET",
Estamos interessados na função
$ (this) .serializeArray () . Na variável $ (this), nosso formulário <form /> entra e é implementado em uma matriz. Ao testá-lo no console, bem como seu
serialize analógico
(), foi determinado que essas funções não carregam arquivos em princípio. Daí a decisão de reescrevê-lo.
Mas primeiro você precisa resolver o problema com o download do arquivo, para isso usamos a classe
FileReader .
$(document).on("change", "form[data-ajax=true] input[type=file]", function (evt) { var form = $($(evt.target).parents("form")[0]); if (evt.target.files.length > 0) { var fileObj = evt.target.files[0]; var reader = new FileReader(); reader.onload = function () { evt.target.setAttribute("data-ajax-image-data", reader.result); form.find("button[type=submit]")[0].classList.remove("disabled"); } reader.onerror = function () { console.log("Error while loading"); form.find("button[type=submit]")[0].classList.remove("disabled"); } form.find("button[type=submit]")[0].classList.add("disabled"); reader.readAsDataURL(fileObj); } });
Um pouco sobre o código.
Primeiro, vinculamos o evento de mudança de entrada, a escolha caiu em "mudança".
Em seguida, verifique se o arquivo está selecionado.
Se o arquivo for selecionado, começamos a fazer o download. O problema era que os dados precisavam ser armazenados em algum lugar; no exemplo, gravaremos os dados no atributo do próprio objeto.
Bloqueie o botão de confirmação até o download do arquivo.
Em caso de erro, escreva isso no console. Esta não é a versão final da função, todos podem atualizá-la para atender às suas necessidades.
Depois de criarmos o carregamento dos dados do arquivo, prosseguimos para a modernização da serialização.
function selfFormSerializeArray(form) { var array = form.serializeArray(); for (var i = 0; i < form[0].length; i++) { if (form[0][i].type === "file") { var fileObj = form[0][i]; var data = fileObj.getAttribute("data-ajax-image-data") || ""; if (data !== "") { array.push({ name: fileObj.name, value: data });
E nós usamos essa função na função principal.
$(document).on("submit", "form[data-ajax=true]", function (evt) { var clickInfo = $(this).data(data_click) || [], clickTarget = $(this).data(data_target), isCancel = clickTarget && (clickTarget.hasClass("cancel") || clickTarget.attr('formnovalidate') !== undefined); evt.preventDefault(); if (!isCancel && !validate(this)) { return; } asyncRequest(this, { url: this.action, type: this.method || "GET", data: clickInfo.concat(selfFormSerializeArray($(this)))
Após a conclusão, você precisa adicionar um processador e um analisador de dados. Com pressa, parece algo assim.
Handler
public PartialViewResult UploadAvatarImage() { if (!ImageHelper.LoadAvatarImage(this.Request.Form["avatarFile"])) { return null; } return PartialView("Null"); }
Ajudante
public static bool LoadAvatarImage(string data) { try { var file = AjaxFile.Create(data); return true; } catch (Exception ex) { return false; }
Analisador
public AjaxFile(string data) { var infos = data.Split(','); this.Type = infos[0].Split(';')[0].Split(':')[1].Split('/')[1]; this.Source = Convert.FromBase64String(infos[1]); ; } public static AjaxFile Create(string data) { return new AjaxFile(data); }
Parabéns! Agora você pode fazer upload de arquivos usando o Ajax padrão para mvc.