Download via OutPutStream

Estou tentando realizar o download de um arquivo .CSV que tenho salvo.
Entretanto o download não aparece pra mim quando eu clico no botão e não aparece nenhum código de erro.

Como posso testar para ver até que ponto esta sendo realizado o procedimento?

Segue o código:

@RequestMapping(value = { "/gerarCsv/" })
	@ResponseBody
	public void gerarCsv(HttpServletRequest request, HttpServletResponse response,
			@RequestParam(value = "inicio", required = true) String inicio,
			@RequestParam(value = "fim", required = true) String fim) {
		try {

			Date dataInicio = new SimpleDateFormat("dd-MM-yyyy").parse(inicio);
			Date dataFim = new SimpleDateFormat("dd-MM-yyyy").parse(fim);

			List<RevogacaoConsolidado> revogacaoConsolidado = revogacao.consultarRevogacaoconsolidado(dataInicio,
					dataFim);

			File arquivo = new File(context.getRealPath("WEB-INF/classes/statics/downloads/revogacao.csv"));

			logger.info("[Recurso:/admin/revogacao/revogacaoPorDataCSV, sessao:" + request.getSession().getId()
					+ ", usuario:" + request.getUserPrincipal().getName() + "]" + "[Caminho ]" + arquivo);

			// Cria arquivo caso não exista.
			if (!arquivo.exists()) {
				arquivo.createNewFile();
			}

			/*
			 * Escreve o arquivo e guarda dentro do caminho desejado objeto arquivo
			 */
			FileWriter fw = new FileWriter(arquivo);
			BufferedWriter bw = new BufferedWriter(fw);

			bw.write("Data" + ";" + "Login" + ";" + "Nome" + ";" + "Sucesso" + ";" + "Erro" + ";" + "Não Cadastrado"
					+ ";" + "Já removido" + ";" + "Total" + ";" + "Porcentagem de Erro %");

			for (RevogacaoConsolidado revog : revogacaoConsolidado) {
				bw.newLine();
				bw.write(revog.getData_processo() + ";" + revog.getLogin() + ";" + revog.getNome() + ";"
						+ revog.getSucesso() + ";" + revog.getErro() + ";" + revog.getNao_cadastrado() + ";"
						+ revog.getJa_removido() + ";" + revog.getTotal() + ";" + revog.getPorcentagem_erro());

			}

			bw.close();
			fw.close();

			/*
			 * realiza o download do conteudo.
			 */
			response.setContentType("application/octet-stream");
			response.setHeader("Content-Disposition", "attachment;filename=revogacao.csv");
			response.setContentLengthLong((int) arquivo.length());

			FileInputStream fileIn = new FileInputStream(arquivo);
			ServletOutputStream out = response.getOutputStream();
			try {

				byte[] outputByte = new byte[4096];
				int lidos = -1;
				while ((lidos = fileIn.read(outputByte)) != -1) {
					out.write(outputByte, 0, lidos);
				}
				fileIn.close();
				out.flush();
				out.close();

				System.out.println("Download de arquivo");
				logger.info("[Recurso:/admin/revogacao/revogacaoPorDataCSV, sessao:" + request.getSession().getId()
						+ ", usuario:" + request.getUserPrincipal().getName() + "]"
						+ "[Verificação de Revogações por data de processado CSV ] [download de arquivo Realizado]");
			} catch (FileNotFoundException ex) {
				ex.printStackTrace();
			}
			logger.info("[Recurso:/admin/revogacao/revogacaoPorDataCSV, sessao:" + request.getSession().getId()
					+ ", usuario:" + request.getUserPrincipal().getName() + "]"
					+ "[Verificação de Revogações por data de processado CSV ]");

		} catch (Exception e) {
			logger.info("[Recurso:/admin/revogacao/revogacaoPorDataCSV, sessao:" + request.getSession().getId()
					+ ", usuario:" + request.getUserPrincipal().getName() + "]"
					+ "[Verificação de Revogações por data de processado] error: " + e);
		}
	}

Obs: Verificando o console do chrome, na aba de Network, vejo que a requisição foi feita e o método chamado com sucesso, foi gerado até um response com os dados gerados. Quando vejo no Timing vejo que houve um tempo para o content Download. Não deveria estar sendo realizado o download do arquivo?

Edit: Este é o response header que o navegador monta. Acredito que esteja correto. Apenas o download não é realizado.

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Disposition: attachment;filename=revogacao.csv
Content-Length: 554
Content-Type: application/octet-stream
Date: Wed, 20 Jan 2021 16:53:42 GMT
Expires: 0
Pragma: no-cache
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

Essa cópia não está certa, você tem que gravar no OutputStream exatamente a quantidade que foi lida do InputStream, você está simplesmente assumindo que sempre são lidos exatamente 4096 bytes, mas pode acontecer do read ler menos bytes, por isso tem que verificar o retorno dele.

Ajuste assim:

byte[] bytes = new byte[4096];
int lidos = -1;
while ((lidos = fileIn.read(bytes)) != -1) {
    out.write(bytes, 0, lidos);
}
fileIn.close();
out.flush();
out.close();

Perfeito. Realizei a alteração conforme mencionou, mas o arquivo de download ainda não aparece no browser quando clico para fazer o download.
Editei a questão trazendo o header que é montado, acredito que esteja correto o mesmo.

Experimenta adicionar o seguinte:

response.setContentLength((int) arquivo.length());

Se ainda não funcionar, tenta mudar o content-type para application/octet-stream.

Ainda não funcionou… novamente ele passa por dentro de todas as validações, monta o cabeçalho corretamente mas não gera o arquivo de download.
Atualizei a pergunta com o método completo que estou utilizando.

Edit: Eu tava debugando e verifiquei que o processo esta correto… mas o que esta estranho é que o arquivo escrito não esta sendo feito o download, mas o conteudo do arquivo esta sendo escrito no response.