How to make the Spring MVC Responseentity return in a new page?

Asked

Viewed 1,179 times

0

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

The problem is that it returns the pdf in the same application tab and this is killing it. How can I 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 calling 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
  • You will not solve this in the backend, you will have to change the link where calls the report

  • Any suggestions how best to do it?

  • Generic <a href="url" target="_blank">Meu link</a>

  • My problem is that I don’t call for a link but for a post in a form that returns a pdf to me through a responseEntity Responseentity.ok(). header(Httpheaders.CONTENT_TYPE, Mediatype.APPLICATION_PDF_VALUE). body(report).

  • Put the part where you call

  • It is the method posted above. Or are you referring to HTML?

  • Anyway I also put HTML

  • The problem is that you send via form, could use ajax for this, send information asynchronously and after you receive open a new window

  • I’m currently at work, when I get home at night I formulate an answer

  • Thank you. I’ll be waiting.

Show 5 more comments

2 answers

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>
        <link rel="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 so I could manipulate the form easier in Javascript.

I 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' });

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

var fileURL = URL.createObjectURL(file);

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

var win = window.open();

The open() interface method Window loads the resource specified in browsing 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 into your browsing context.

win.document.write()

Write inside a Document

The last line of the function is a way to bypass 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 defined in 100%

  • 1

    Thanks - Thanks, I’ll try.

-2

You can put the following tag in the form target="_Blank"

Browser other questions tagged

You are not signed in. Login or sign up in order to post.