2
respostas

Upload de arquivo com dados do formulário

Bom dia Pessoal, tudo bem?

Preciso de uma ajuda por favoor! rs

Vamos lá! Eu tenho um formulário de cadastro e nele estou passando um JSON para o Back-End, até aí ok, começou a complicar quando decidi que iria upar uma imagem no mesmo formulário. Como faço isso via ajax? E como recebo meus dados no Back-End? Vou passar o JSON separado do MultiPartFile? Alguma sugestão?

Segue minha função atual JS que passa os arquivos para o Back-End:

function cadastrar_aluno() {
    var faculdade = {};
    faculdade["codigo"] = $("#sel-faculdade option:selected").val();
    faculdade["nome"] = $("#sel-faculdade option:selected").text();

    var dadosbeneficios = $("#sel-beneficio-incluso").select2('data');
    var codbeneficios = $("#sel-beneficio-incluso").select2('val');

    var beneficios = [];

    for(i = 0; i < dadosbeneficios.length; i++){
        var beneficio = {
                codigo: codbeneficios[i],
                descricao: dadosbeneficios[i].text
        };
        beneficios.push(beneficio);
    }

    var dadoslocaisprox = $("#sel-local-util-proximo").select2('data');
    var codlocaisprox = $("#sel-local-util-proximo").select2('val');
    var locaisprox = [];

    for(i = 0; i < dadoslocaisprox.length; i++){
        var localprox = {
            codigo:    codlocaisprox[i],  
            descricao: dadoslocaisprox[i].text
        };

        locaisprox.push(localprox);
    }

    var aluno = {};
    aluno["nome"] = $("#nome").val();
    aluno["cpf"] = $("#cpf").val();
    aluno["telefone"] = $("#telefone").val();
    aluno["celular"] = $("#celular").val();
    aluno["email"] = $("#email").val();
    aluno["senha"] = $("#senha").val();
    //aluno["fotoPath"] = $("#foto-path").val();
    aluno["faculdade"] = faculdade;
    aluno["beneficiosInclusos"] = beneficios;
    aluno["locaisUteisProximos"] = locaisprox;

    $.ajax({
        type: "POST",
        contentType: "application/json",
        url: "/usuario/cadastraraluno",
        data: JSON.stringify(aluno),
        dataType: 'json',
        cache: false,
        timeout: 600000,
        success: function (data) {

            var json = "<h4>Ajax Response</h4><pre>"
                + JSON.stringify(data, null, 4) + "</pre>";
            $('#feedback').html(json);

            console.log("SUCCESS : ", data);
            $("#btn-search").prop("disabled", false);

        },
        error: function (e) {

            var json = "<h4>Ajax Response</h4><pre>"
                + e.responseText + "</pre>";
            $('#feedback').html(json);

            console.log("ERROR : ", e);
            $("#btn-search").prop("disabled", false);

        }
    });

}

Segue meu método Back-End atual que recebe meu JSON Aluno:

@PostMapping(value = "/cadastraraluno", consumes= MediaType.APPLICATION_JSON_VALUE)
    public void cadastrarUsuario(Aluno aluno) {

        System.out.println(aluno);
        System.out.println("Telefone: " + aluno.getTelefone());
        System.out.println("Celular: " + aluno.getCelular());
        System.out.println("Email: " + aluno.getEmail());
        System.out.println("Senha: " + aluno.getSenha());
        System.out.println("Faculdade: " + aluno.getFaculdade());
        System.out.println("Beneficios Inclusos: " + aluno.getBeneficiosInclusos());
        System.out.println("Locais Utéis Próx.: " + aluno.getLocaisUteisProximos());
        System.out.println("Faixa Preço: " + aluno.getFaixaPreco());
        //alunoRepository.save(aluno);
    }

Alguém tem alguma ideia de como devo prosseguir?

Se puderem me ajudar serei muuito grato! Muito obrigado pela atenção desde já!

2 respostas

Fala Tiago, tudo bem ?

Imagino que o problema aí é que a requisição não será feita com o enctype multipart/form-data.

Não sei ao certo como a api do jQuery dá suporte aos requests do tipo multipart. Mas é possível (e bem simples) fazer com a própria fetch API do JavaScript.

Veja um exemplo:

function send() {
        const input = document.querySelector('#productPhoto');
        const uploadedFile = input.files[0];

        const data = new FormData();
        data.append('nome', document.querySelector('#productName').value)
        data.append('foto', uploadedFile)

        const requestDetails = {
            method: 'POST',
            body: data
        }

        fetch('http://localhost:8080/upload', requestDetails)
            .then(response => {

                if(!response.ok) 
                    throw new Error('Não foi possível enviar arquivo ao servidor');

                return response.text();
            })
            .then(text => {
                const p = document.createElement('p');
                p.textContent = text;

                document.querySelector('body').appendChild(p); 
            })
            .catch(error => alert(error.message));

    }

Imagine que pra esse caso temos um simples HTML, contendo dados de um produto. Um nome e uma foto:

<h1>Novo Produto</h1>

    <div>
        <label for="productName">Nome: </label><br />
        <input type="text" id="productName"/>
    </div>

    <div>
        <label for="productPhoto">Foto:</label><br />
        <input type='file' id="productPhoto" />
    </div>

    <button onclick="send()">Enviar</button>

Podemos trabalhar com o objeto de FormData que já abstrai a complexidade de fazer uma requisição com o enctype correto. Chamamos append() para cada dado que queiramos enviar, incluindo a representação do arquivo capturada do input file. Não sei ao certo como você está esperando esses dados no servidor, dado que estava mandando um JSON, mas esperar por representações da Produto produto e MultipartFile foto no seu controller já será suficiente pro Spring montar suas informações.

PS: Usei assim recentemente em um projeto e funcionou bonitinho

Espero ter ajudado. Abraço!

É Vraptor, mas é só adaptar o controller pra spring

    <div id="modalLancamento" class="modal fade">
        <div class="modal-dialog">
            <form method="post" id="lancamento-form" enctype="multipart/form-data">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal">&times;</button>
                        <h4 class="modal-title">Adicionar Lançamento</h4>
                    </div>
                    <div class="modal-body">
                        <label>Título</label> <input type="text" id="titulo"
                            name="lancamento.titulo" class="form-control" />
                            <label for="autor" class="control-label">Autor:</label> <select
                                name="lancamento.autor.congressistaId" class="form-control" id="select-autores">
                            </select>
                            <label>Sinopse</label> <input type="text" id="sinopse"
                            name="lancamento.sinopse" class="form-control" />
                            <label>Saiba mais em:</label> <input type="text" id="observacao"
                            name="lancamento.observacao" class="form-control" />
                             <label>Selecione
                            a Capa</label> <input type="file" id="fie" name="file"><br/> <span
                            id="uploaded_image"></span>
                    </div>
                    <div class="modal-footer">

                    <input  type="hidden" name="lancamento.lancamentoId" id="lancamento-id">
                    <input  type="hidden" name="lancamento.capa" id="lancamento-capa">
                        <input type="submit" id="action" name="action"
                            class="btn btn-success" value="Adicionar">
                    </div>
                </div>
            </form>
        </div>
    </div>
$(document).on("submit","#lancamento-form",function(event){
                event.preventDefault();

               $.ajax(
                       {
                           "url":'<c:url value="/lancamentos/salvar" />',
                           "method":"post",
                           "dataType":'json',
                           "data": new FormData(this),
                           "contentType":false,
                           "processData":false
                           }
                       ).done(function(data){
                           $("#lancamento-form :input").val('');
                           $("#modalLancamento").modal("hide");
                           table.ajax.reload();
                           }).fail(function(jqXHR, status, errorThrown ){

                               var obj = jQuery.parseJSON(jqXHR.responseText);
                               var erros = [];    
                                erros = obj.errors;
                                 var errorsHtml= '';
                                 $.each( erros, function( key, value ) {
                                     errorsHtml += '<li>' + erros[key].message + '</li>'; 
                                 });
                                 swal('Oops!', errorsHtml, 'error');



                               });

                });
@Controller
@RequestScoped
public class LancamentoController {

    @Inject
    private LancamentoRepository lancamentoRepository;

    @Inject
    private Result result;
    @Inject
    private HttpServletRequest request;
    @Inject
    private Validator validator;


    @Post("/lancamentos/salvar")         
    public void salvar(@Valid Lancamento lancamento,UploadedFile file){


        validator.onErrorSendBadRequest();


        if(file != null){

            String novoNome = Normalizer.normalize(file.getFileName(), Normalizer.Form.NFD);
            novoNome = novoNome.replaceAll("[^\\p{ASCII}]", "");
            novoNome = UUID.randomUUID()+ novoNome;    

            if(file != null){
            lancamento.setCapa(novoNome);
            }

            try(FileOutputStream fos = new FileOutputStream(new File(
                    local.toAbsolutePath().toString() + FileSystems.getDefault().getSeparator() 
                    + FileSystems.getDefault().getSeparator() +lancamento.getCapa()))){
                file.writeTo(fos);
                file.getFile().close();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("Erro ao subir foto.");

            }
        }
        if(lancamento.getLancamentoId() != null){

            lancamentoRepository.atualizar(lancamento);
        }

Adaptei deste exemplo: http://www.webslesson.info/2017/01/php-pdo-ajax-crud-with-data-tables-and-bootstrap-modals.html