Bug ao salvar dados de um formulário em JSP

Bom dia a todos, estou enfrentando o seguinte problema , tenho um formulário no qual está gravando as informações no banco de dados e está sendo visualizado na tabela do meu frontend , no meu formulário eu tenho o campo imagem no qual estou carregando utilizando javascript no meu input está do tipo file e estou utilizando onchange , isso está fazendo que ao carregar a imagem ele da um post antes de eu mandar salvar todas as informações do formulário, sendo assim a imagem está sendo gravada em campos diferente com outro id, sendo que eu queria que ficasse tudo no mesmo campo os dados da pessoa e a foto. já utilizei o enctype="multipart/form-data" mas não resolveu vou enviar meu código para vocês darem uma olhada.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>


<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>CADASTRO DE VISITANTES</title>
<!-- INICIO DO LINK JQUERY PARA UPLOAD DE IMAGEM -->
<script type="text/javascript"
    src="https://code.jquery.com/jquery-3.5.0.min.js"></script>
<!-- FIM DO LINK JQUERY PARA UPLOAD DE IMAGEM -->
</head>
<body>

    <!-- AQUI COMEÇA O CÓDIGO PARA REALIZAR PESQUISA DE VISITANTES NO SISTEMA -->

    <div>
        <form class="search" action="PesquisarVisitante" method="POST">

            <input id="txbusca" name="pesquisa" type="text" value=""
                placeholder="Digite o que você procura" /> <input id="btnBusca"
                type="submit" value="Pesquisar" /> <input type="submit"
                value="Voltar" /> <input TYPE="button" VALUE="Home"
                onclick="window.location.href='menu.jsp'">


        </form>

    </div>
    <!-- AQUI TERMINA O CÓDIGO PARA REALIZAR PESQUISA DE VISITANTES NO SISTEMA -->




    <h1>BEM VINDOS A TELA DE CADASTRO DE VISITANTES</h1>

    <!-- AQUI COMEÇA O CÓDIGO DO FORMULARIO PARA CADASTRO DE VISITANTES -->
    <form action="VisitanteServlet" method="post"
        enctype="multipart/form-data">

        <table>

            <tr>

                <td><input type="text" id="id" name="id" hidden=""
                    value="${usuario.id }" /></td>
            </tr>

            <tr>
                <td>Nome</td>
                <td><input type="text" required id="nome" name="nome"
                    value="${usuario.nome }" /></td>
            </tr>

            <tr>
                <td>CPF</td>
                <td><input type="text" required id="cpf" name="cpf"
                    value="${usuario.cpf }" /></td>
            </tr>

            <tr>
                <td>RG</td>
                <td><input type="text" required id="rg" name="rg"
                    value="${usuario.rg }" /></td>
            </tr>


            <tr>
                <td>FONE</td>
                <td><input type="text" required id="telefone" name="telefone"
                    value="${usuario.telefone }" /></td>
            </tr>


            <tr>
                <td>DataHora</td>
                <td><input type="datetime-local" required id="datetime"
                    name="datetime" value="${usuario.datetime }" /></td>
            </tr>


            <tr>
                <td>Destino</td>
                <td><input type="text" required id="destino" name="destino"
                    value="${usuario.destino }" /></td>
            </tr>

            <tr>
                <td>Motivo</td>
                <td><input type="text" required id="motivo" name="motivo"
                    value="${usuario.motivo }" /></td>
            </tr>

            <tr>
                <td><img alt="Imagem" src="" id="target" width="200" height="200">

                <input type="file" id="foto" name="foto" width="200" height="200"
                    onchange="uploadFile();" /></td>

            </tr>
            <tr>

                <td><input type="submit" value="Salvar" /></td>
                <td><input type="reset" value="Cancelar" /></td>
            </tr>

        </table>

    </form>









    <!--  <td><a href="VisitanteServlet"></a></td> -->



    <!-- AQUI TERMINA O CÓDIGO DO FORMULARIO PARA CADASTRO DE VISITANTES -->

    <br />
    <br />

    <!-- AQUI COMEÇA O CÓDIGO PARA VISUALIZAR OS CADASTRO DE VISITANTES -->



    <table border="1">

        <tr>

            <th>ID</th>
            <th>Nome</th>
            <th>CPF</th>
            <th>RG</th>
            <th>FONE</th>
            <th>DataHora</th>
            <th>Destino</th>
            <th>Motivo</th>
            <th>Foto</th>

            <th>Excluir</th>
            <th>Editar</th>


        </tr>

        <c:forEach items="${visitantes}" var="usuario">


            <tr>

                <td><c:out value="${usuario.id }"></c:out></td>
                <td><c:out value="${usuario.nome }"></c:out></td>
                <td><c:out value="${usuario.cpf}"></c:out></td>
                <td><c:out value="${usuario.rg}"></c:out></td>
                <td><c:out value="${usuario.telefone}"></c:out></td>
                <td><c:out value="${usuario.datetime}"></c:out></td>
                <td><c:out value="${usuario.destino}"></c:out></td>
                <td><c:out value="${usuario.motivo}"></c:out></td>
                <td><img width="200" height="200"
                    src='<c:out value="${usuario.foto}"/>'></td>



                <!-- AQUI COMEÇA O COMANDO PARA DELETAR LOGIN E ATUALIZAR LOGIN -->

                <td><a
                    href="VisitanteServlet?acao=deletar&usuario=${usuario.id}">Excluir</a></td>
                <td><a
                    href="VisitanteServlet?acao=editar&usuario=${usuario.id}">Editar</a></td>



                <!-- AQUI TERMINA O COMANDO PARA DELETAR LOGIN E ATUALIZAR LOGIN -->



            </tr>


        </c:forEach>



    </table>

    <!-- AQUI TERMINA O CÓDIGO PARA VISUALIZAR OS CADASTRO DE LOGINS -->



</body>


<!--  AQUI COMEÇA O CÓDIGO DO JAVASCRIPT  -->

<script type="text/javascript">
    function uploadFile() {
        var target = document.querySelector("img");
        var file = document.querySelector("input[type=file]").files[0];

        var reader = new FileReader();

        reader.onloadend = function() {

            target.src = reader.result;

            // Upload Ajax
            $.ajax({
                method : "POST",
                enctype : 'multipart/form-data',
                url : "VisitanteServlet",
                data : {
                    foto : reader.result
                }
            }).done(function(response) {
                //alert("Sucesso: " + response);
            }).fail(function(xhr, status, errorThrown) {
                //alert("Error: " + xhr.responseText);
            });
        };

        if (file) {
            reader.readAsDataURL(file);
        } else {
            target.src = "";
        }
    }
</script>

<!--  AQUI TERMINA O CÓDIGO DO JAVASCRIPT  -->


</html>

O problema eh que o seu onchange também está realizando um POST para o servlet VisitanteServlet. Com isso, ao submeter o formulário de cadastro de visitantes, a imagem será enviada novamente.

É isso mesmo o problema porém não sei como resolver , você teria alguma dica ?

Eu tentaria tirar o onchange do input file.

Eu tentei tirar , mas sem ele não funciona meu script em javascript com ajax para transformar a imagem em Base64, se eu te enviar o projeto você poderia está me ajudando ?

Quando vc faz submit no formulário, o arquivo do input file não chega na servlet não?

Quando eu faço um submit ele grava a imagem, porém a imagem fica em um outro campo com um Id diferente, quando eu carrego a imagem o onchange está dando submit também

Como assim? Manda o código do servlet que recebe essa imagem e grava ela.

Ok vou enviar agora

Essa é minha Servlet

package servlets;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import beans.VisitanteBean;
import daos.CadastrarVisitanteDao;


@WebServlet("/pages/VisitanteServlet")
public class VisitanteServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    
    public VisitanteServlet() {
        super();
       
    }

	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		 		
		try {

			// PARAMETROS PARA REALIZAR AÇÕES DE ELETAR ATUALIZAR E EXCLUIR E PESQUISAR
			CadastrarVisitanteDao dao = new CadastrarVisitanteDao();
			String acao = request.getParameter("acao");
			String usuario = request.getParameter("usuario");

			if (acao.equalsIgnoreCase("deletar")) {

				dao.deletarVisitante(usuario);

				RequestDispatcher dispatcher = request.getRequestDispatcher("cadastrovisitante.jsp");
				request.setAttribute("visitantes", dao.listarVisitante());
				dispatcher.forward(request, response);

			} else if (acao.equalsIgnoreCase("listartodos")) {

				dao.listarVisitante();

				RequestDispatcher dispatcher = request.getRequestDispatcher("cadastrovisitante.jsp");
				request.setAttribute("visitantes", dao.listarVisitante());
				dispatcher.forward(request, response);

			} else if (acao.equalsIgnoreCase("editar")) {

				VisitanteBean visitante = dao.consultarAtualizarVisitante(usuario);

				RequestDispatcher dispatcher = request.getRequestDispatcher("cadastrovisitante.jsp");
				request.setAttribute("usuario", visitante);
				dispatcher.forward(request, response);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		

		try {

			// AQUI COMEÇA O CÓDIGO PARA IMPLEMENTAR O METODO DE SALVAR VISITANTE ATUALIZAR E VALIDAR

			String id = request.getParameter("id");
			String nome = request.getParameter("nome");
			String cpf = request.getParameter("cpf");
			String rg = request.getParameter("rg");
			String telefone = request.getParameter("telefone");
			String datetime = request.getParameter("datetime");
			String destino = request.getParameter("destino");
			String motivo = request.getParameter("motivo");
			String foto = request.getParameter("foto");
			//System.out.println(foto);
			//String typefoto = request.getParameter("typefoto");
			
			
			

			CadastrarVisitanteDao dao = new CadastrarVisitanteDao();
			VisitanteBean visitante = new VisitanteBean();
			
			
			//visitante.setId(!id.isEmpty() ? Long.parseLong(id) : 0);
			//visitante.setId(id !=null && id != "" ? Long.parseLong(id) : 0);
			visitante.setId(id !=null && id != "" ? Long.parseLong(id) : null);
			//visitante.setId(Long.parseLong(id));
			
			visitante.setNome(nome);
			visitante.setCpf(cpf);
			visitante.setRg(rg);
			visitante.setTelefone(telefone);
			visitante.setDatetime(datetime);
			visitante.setDestino(destino);
			visitante.setMotivo(motivo);
			visitante.setFoto(foto);
			
			

			if (id == null || id.isEmpty() && dao.consultarVisitanteRepetido(cpf) ) {

				dao.cadastrarVisitante(visitante);

			} else {

				dao.atualizarVisitante(visitante);

				
			}

			// AQUI TERMINA O CÓDIGO PARA IMPLEMENTAR O METODO DE SALVAR VISITANTE ATUALIZAR E VALIDAR
		}

		catch (Exception e) {
			e.printStackTrace();
			
		}

		// AQUI COMEÇA O CÓDIGO PARA VISUALIZAR OS VISITANTES CADASTRADOS
		try {
			CadastrarVisitanteDao dao = new CadastrarVisitanteDao();

			RequestDispatcher view = request.getRequestDispatcher("cadastrovisitante.jsp");

			request.setAttribute("visitantes", dao.listarVisitante());

			view.forward(request, response);

		} catch (Exception e) {
			e.printStackTrace();
		}

		// AQUI TERMINA O CÓDIGO PARA VISUALIZAR OS VISITANTES CADASTRADOS
	}
}

Voce deve fazer com que os dados do visitante e a foto seja enviada no mesmo request. Do jeito que está as fotos vai num request e os dados está indo em outro, com isso, serão gravados em registros diferentes (inclusive, quando a foto é submetida pelo javascript, imagino que todos os outros dados estão chegando null no servlet).

Veja um exemplo de um formulário com upload:

Formulário na JSP

<form action="upload" method="post" enctype="multipart/form-data">
    <input type="text" name="descricao" />
    <input type="file" name="foto" />
    <input type="submit" />
</form>

Servlet

@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String descricao = request.getParameter("descricao");
		Part fotoPart = request.getPart("foto");
		String fileName = Paths.get(fotoPart.getSubmittedFileName()).getFileName().toString();
		InputStream conteudoFoto = fotoPart.getInputStream();
		// Aqui vc pega o inputstream, lê os bytes e guarda o arquivo no banco, no filesystem, etc.
	}
}

Eu queria ter somente um formulário para enviar os dados do visitante e a foto e apenas uma Servlet para o formulário do visitante isso é possível ?

Se não for abusar da sua boa vontade você poderia me ajudar por TeamViewer ?
queria resolver apenas essa parte, meu sistema está tudo funcionando porém queria só resolver esse bug da imagem que está sendo gravada em outro campo com outro ID

Sim. Vc precisa apenas de um formulário para os dados e a foto do visitante. Isso está no exemplo que coloquei.

Más já estou fazendo isso, meu formulário contem os dados do visitante incluindo o campo foto, mas está com bug !

Então, o bug é por conta da função javascript que está executando uma nova requisição via ajax, e isso não deve acontecer dessa forma. Ou tu faz a requisição completa via ajax ou via form submit.

No exemplo que passei, vc pode dispensar o uso da função javascript e deixar o envio da foto + os dados do visitante pelo formulário via submit.

E como vai ser feita a requisição para Base64 ? Estou usando javascript com ajax porque ele transforma minha imagem no formato Base64.

Se não for abusar da sua boa vontade você poderia me ajudar por TeamViewer ?
queria resolver apenas essa parte, meu sistema está tudo funcionando porém queria só resolver esse bug da imagem que está sendo gravada em outro campo com outro ID, talvez seja algum coisa simples que estou deixando passar e não estou percebendo !

Não precisa, pois, no exemplo que passei, a linha Part fotoPart = request.getPart("foto"); já recupera o arquivo, e a linha InputStream conteudoFoto = fotoPart.getInputStream(); recupera o conteúdo.

Mesmo tentando esse procedimento não consegui, agradeço muito a sua ajuda, caso você consiga me dar um suporte remoto vou ficar muito agradecido. !