Domanda

MODIFICA: Vedi il mio codice di lavoro nelle risposte di seguito.


In breve: ho un file JSP che chiama un metodo in un bean Java. Questo metodo crea un file PDF e, in teoria, lo restituisce al JSP in modo che l'utente possa scaricarlo. Tuttavia, durante il caricamento del PDF, Adobe Reader genera l'errore: Il file non inizia con '% PDF-' .

In dettaglio: Finora, il JSP chiama correttamente il metodo, il PDF viene creato e quindi il JSP sembra fornire all'utente il file PDF finito. Tuttavia, non appena Adobe Reader tenta di aprire il file PDF, viene visualizzato un errore: Il file non inizia con '% PDF-' . Per buona misura, ho il metodo di creare il PDF sul mio desktop in modo da poterlo controllare; quando lo apro normalmente in Windows sembra andare bene. Quindi perché l'output dal JSP è diverso?

Per creare il PDF, sto usando Apache FOP . Sto seguendo uno dei loro esempi più elementari, ad eccezione del passaggio del PDF risultante a un JSP anziché semplicemente salvarlo sul computer locale. Ho seguito il loro modello di utilizzo di base e questo codice di esempio .

Ecco il mio file JSP:

<%@ taglib uri="utilTLD" prefix="util" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ page language="java" session="false" %>
<%@ page contentType="application/pdf" %>

<%-- Construct and initialise the PrintReportsBean --%>
<jsp:useBean id="printReportsBean" scope="request" class="some.package.printreports.PrintReportsBean" />
<jsp:setProperty name="printReportsBean" property="*"/>

<c:set scope="page" var="xml" value="${printReportsBean.download}"/>

Ecco il mio metodo Java Bean:

//earlier in the class...
private static FopFactory fopFactory = FopFactory.newInstance();

public File getDownload() throws UtilException {

    OutputStream out = null;
    File pdf = new File("C:\\documents and settings\\me\\Desktop\\HelloWorld.pdf");
    File fo  = new File("C:\\somedirectory", "HelloWorld.fo");

    try {

        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        out = new FileOutputStream(pdf);
        out = new BufferedOutputStream(out);

        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(); //identity transformer

        Source src = new StreamSource(fo);

        Result res = new SAXResult(fop.getDefaultHandler());

        transformer.transform(src, res);

        return pdf;

    } catch (Exception e) {

         throw new UtilException("Could not get download. Msg = "+e.getMessage());

    } finally {

         try {
             out.close();
         } catch (IOException io) {
             throw new UtilException("Could not close OutputStream. Msg = "+io.getMessage());
         }
    }
}

Mi rendo conto che questo è un problema molto specifico, ma qualsiasi aiuto sarebbe molto apprezzato!

È stato utile?

Soluzione

Il modo in cui ho implementato questo tipo di funzionalità in passato è di fare in modo che un servlet scriva il contenuto del file PDF nella risposta come flusso. Non ho più il codice sorgente con me (ed è stato almeno un anno da quando ho fatto qualsiasi lavoro servlet / jsp), ma ecco cosa potresti provare:

In un servlet, ottenere un handle sul flusso di output della risposta. Cambia il tipo mime della risposta in " application / pdf " ;, e fai in modo che il servlet esegua la gestione dei file che hai nel tuo esempio. Solo, invece di restituire l'oggetto File, il servlet deve scrivere il file nel flusso di output. Vedi esempi di file i / o e sostituisci semplicemente le righe outfile.write (...) con responseStream.write (...) e dovresti essere impostato per andare. Dopo aver svuotato e chiuso il flusso di output e fatto il ritorno, se ricordo bene, il browser dovrebbe essere in grado di raccogliere il pdf dalla risposta.

Altri suggerimenti

Ok, ho funzionato. Ecco come l'ho fatto:

JSP:

<%@ taglib uri="utilTLD" prefix="util" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ page language="java" session="false" %>
<%@ page contentType="application/pdf" %>

<%-- Construct and initialise the PrintReportsBean --%>
<jsp:useBean id="printReportsBean" scope="request" class="some.package.PrintReportsBean" />
<jsp:setProperty name="printReportsBean" property="*"/>

<%
    // get report format as input parameter     
    ServletOutputStream servletOutputStream = response.getOutputStream();

    // reset buffer to remove any initial spaces
    response.resetBuffer(); 

    response.setHeader("Content-disposition", "attachment; filename=HelloWorld.pdf");

    // check that user is authorised to download product
    printReportsBean.getDownload(servletOutputStream);
%>

Metodo Java Bean:

//earlier in the class...
private static FopFactory fopFactory = FopFactory.newInstance();

public void getDownload(ServletOutputStream servletOutputStream) throws UtilException {

    OutputStream outputStream = null;

    File fo  = new File("C:\\some\\path", "HelloWorld.fo");

    try {

        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        outputStream = new BufferedOutputStream(servletOutputStream);

        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, outputStream);

        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(); //identity transformer

        Source src = new StreamSource(fo);

        Result res = new SAXResult(fop.getDefaultHandler());

        transformer.transform(src, res);

    } catch (Exception e) {

        throw new UtilException("Could not get download. Msg = "+e.getMessage());

    } finally {

        try {
            outputStream.close();
        } catch (IOException io) {
            throw new UtilException("Could not close OutputStream. Msg = "+io.getMessage());
        }
     }
 }

Grazie a tutti per il loro contributo!

Solo un'ipotesi, ma hai controllato il tipo MIME che la tua pagina JSP sta tornando?

modifica: se in realtà leggessi il codice che hai pubblicato vedrei che l'hai impostato, quindi non importa :)

edit2: Le nuove righe tra i tag JSP nel tuo codice JSP non finiranno nel flusso di output? Potrebbe buttare via la risposta restituita dal server? Non so nulla del formato di un PDF, ma dipende da alcuni "marker" personaggi che si trovano in determinate posizioni nel file? (Il messaggio di errore restituito suona in questo modo).

Sono d'accordo con matt b , forse sono gli spazi tra i tag JSP. Prova a mettere la direttiva

<%@ page trimDirectiveWhitespaces="true" %>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top