How do the Spring MVC ResponseEntity return on a new page?

0

I have a method of a report controller (posted below), to which I get a PDF.

The problem is that it returns the pdf on the same application tab and this is killing it. How can I do to return in a new tab?

Post method that is submitted in html.

@PostMapping("/vendasEmitidas")
public ResponseEntity<byte[]> 
   gerarRelatorioVendasEmitidas(PeriodoRelatorio periodoRelatorio) 
   throws SQLException, JRException {

    byte[] relarotio = 
      relatorioService.gerarRelatorioVendasEmitidas(periodoRelatorio);

    return ResponseEntity
       .ok()
       .header(HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_PDF_VALUE)
       .body(relarotio);

}

HTML that calls the report

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org"
    xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
    layout:decorate="~{layout/LayoutPadrao}">

<head>
    <title>Relatório - Vendas Emitidas</title>
</head>

<section layout:fragment="conteudo">

    <div class="page-header">
        <div class="container-fluid">
            <h1>
                Relatório de vendas emitidas
            </h1>
        </div>
    </div>

    <div class="container-fluid">
        <form method="POST" th:object="${periodoRelatorio}" th:action="@{/relatorios/vendasEmitidas}">
            <th:block th:include="fragments/MensagensErroValidacao"></th:block>

            <div class="row">
                <div class="form-group  col-sm-12">
                    <label for="dataInicio">Data de criação</label>
                    <div class="form-inline">
                        <input type="text" class="form-control  aw-form-control-inline-sm  js-date" 
                            id="dataInicio" th:field="*{dataInicio}" autocomplete="off"/>
                        <label for="a" class="aw-form-label-between">a</label>
                        <input type="text" class="form-control  aw-form-control-inline-sm  js-date" 
                            id="dataFim" th:field="*{dataFim}" autocomplete="off"/>
                    </div>
                </div>
            </div>

            <button type="submit" class="btn  btn-primary">Emitir</button>
        </form>
    </div>
</section>

</html>

I'm using:

  • Spring MVC 5.0.2
  • SpringBoot 2
  • Jasper
  • Thymeleaf
asked by anonymous 05.02.2018 / 00:18

1 answer

1

I got the report to open in another tab, your code will look like this:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layout/LayoutPadrao}">

    <head>
        <title>Relatório - Vendas Emitidas</title>
        <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script><linkrel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"/>
        <script>
            $(document).ready(function() {
                var form = $('#form');
                form.submit(function (e) {
                    e.preventDefault();
                    var dados = form.serialize();
                    $.post({
                        url: form.attr('action'),
                        data: {
                            dados: dados
                        },
                        success: function (data) {
                            var file = new Blob([data], { type: 'application/pdf' });
                            var fileURL = URL.createObjectURL(file);
                            var win = window.open();
                            win.document.write('<iframe src="' + fileURL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;"></iframe>')
                        },
                        error: function(data) {
                            console.log(data);
                        }
                    });
                });
            })
        </script>
    </head>

    <section layout:fragment="conteudo">

        <div class="page-header">
            <div class="container-fluid">
                <h1>
                    Relatório de vendas emitidas
                </h1>
            </div>
        </div>
        <div class="container-fluid">
            <form method="POST" th:object="${periodoRelatorio}" th:action="@{/relatorios/vendasEmitidas}" id="form">
                <div class="row">
                    <div class="form-group  col-sm-12">
                        <label for="dataInicio">Data de criação</label>
                        <div class="form-inline">
                            <input type="text" class="form-control  aw-form-control-inline-sm  js-date"
                                   id="dataInicio" th:field="*{dataInicio}" autocomplete="off"/>
                            <label for="a" class="aw-form-label-between">a</label>
                            <input type="text" class="form-control  aw-form-control-inline-sm  js-date"
                                   id="dataFim" th:field="*{dataFim}" autocomplete="off"/>
                        </div>
                    </div>
                </div>
                <button type="submit" class="btn  btn-primary">Emitir</button>
            </form>
        </div>
    </section>
</html>

The only thing I changed in the structure of your HTML was the id attribute, I added it to be able to manipulate the form in an easier way in Javascript.

I've added the following script to your code:

$(document).ready(function() {
    var form = $('#form'); //Pega o formulário pelo id
    form.submit(function (e) { // Executa a função ao clicar o botão submit do formulário
        e.preventDefault(); // Previne a página de dar submit e direcionar para o action do form
        var dados = form.serialize(); // Transforma os dados do formulário para que sejam passados via ajax
        $.post({ //Faz uma requisição ajax com o método POST
            url: form.attr('action'), // Define a url a ser acessada
            data: {
                dados: dados //Dados a serem enviados
            },
            success: function (data) { // Função que será executa em caso de sucesso
                var file = new Blob([data], { type: 'application/pdf' });
                var fileURL = URL.createObjectURL(file);
                var win = window.open();
                win.document.write('<iframe src="' + fileURL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;"></iframe>')
            },
            error: function(data) { // Função a ser executada em caso de falha
                console.log(data);
            }
        });
    });
})

The important part of the code is this:

function (data) {

  

Date is the information received in the request

var file = new Blob([data], { type: 'application/pdf' });

  

A Blob object represents an object, of the file type, with data   immutable gross. Blobs represent data that is not   necessarily in a native JavaScript format. The File interface is   based on Blob, inheriting blob functionality and expanding it to   support user system files.

var fileURL = URL.createObjectURL(file);

  

Creates a new URL object whose lifetime is linked to the document in   window in which this object was created. The new URL object represents the   File object or the Blob object passed as argument.

var win = window.open();

  

The open () method of the Window interface loads the resource specified in   navigation context (window, <iframe> or tab) with the name   specified. If the name does not exist, a new window opens and the   specified resource is loaded in its navigation context.

win.document.write()

  

Write in a document

The last line of the function is a way around a problem with Chrome :

'<iframe src="' + fileURL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;"></iframe>'
  

Specifies a iframe having as content the file that was received from the server, without borders and with height / width set to 100%

    
06.03.2018 / 02:43