2008-10-20 26 views
1

EDIT: Voir my working code dans les réponses ci-dessous.Renvoyer un fichier PDF d'un Java Bean à un JSP


En bref: Je dispose d'un fichier JSP qui appelle une méthode dans un Java Bean. Cette méthode crée un fichier PDF et, en théorie, le renvoie au JSP afin que l'utilisateur puisse le télécharger. Toutefois, lors du chargement du fichier PDF, Adobe Reader affiche l'erreur suivante: Le fichier ne commence pas par '% PDF-'.

En détail: Jusqu'à présent, la JSP appelle la méthode avec succès, le PDF est créé et le fichier JSP apparaît pour donner à l'utilisateur le fichier PDF fini. Cependant, dès qu'Adobe Reader essaie d'ouvrir le fichier PDF, une erreur se produit: Le fichier ne commence pas par '% PDF-'. Juste pour faire bonne mesure, j'ai la méthode créer le PDF sur mon bureau afin que je puisse le vérifier; quand je l'ouvre normalement dans Windows, cela semble bien. Alors pourquoi la sortie de la JSP est-elle différente?

Pour créer le PDF, j'utilise Apache FOP. Je suis l'un de leurs exemples les plus basiques, à l'exception de passer le PDF résultant à un JSP au lieu de simplement l'enregistrer sur la machine locale. J'ai suivi leurs basic usage pattern et this example code.

Voici mon fichier 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}"/> 

Voici ma méthode 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()); 
     } 
    } 
} 

Je me rends compte que cela est un problème très spécifique, mais toute aide serait grandement appréciée!

Répondre

4

La façon dont j'ai implémenté ce type de fonctionnalité dans le passé est de faire en sorte qu'une servlet écrit le contenu du fichier PDF dans la réponse sous forme de flux. Je n'ai plus le code source avec moi (et cela fait au moins un an que je n'ai pas fait de servlet/jsp), mais voici ce que vous pouvez essayer:

Dans une servlet, obtenez un gérer sur le flux de sortie de la réponse. Changez le type mime de la réponse à "application/pdf", et demandez à la servlet de faire le traitement de fichier que vous avez dans votre exemple. Seulement, au lieu de renvoyer l'objet File, demandez au servlet d'écrire le fichier dans le flux de sortie. Voir des exemples de fichier I/O et juste remplacer toutes les lignes outfile.write (...) avec responseStream.write (...) et vous devriez être réglé pour aller. Une fois que vous rincer et fermer le flux de sortie, et faire le retour, si je me souviens bien, le navigateur devrait être en mesure de ramasser le pdf de la réponse.

3

Juste une supposition, mais avez-vous vérifié le type MIME que votre page JSP renvoie?

edit: si je lis en fait le code affiché je vous voir positionniez, alors tant pis :)

Edit2: ne sont pas les nouvelles lignes entre les balises JSP dans votre code JSP va finir dans la flux de sortie? Cela pourrait-il rejeter la réponse renvoyée par le serveur? Je ne sais rien sur le format d'un PDF, mais cela dépend-il de certains caractères "marqueurs" se trouvant à certains endroits dans le fichier? (Le message d'erreur renvoyé ressemble à cela).

0

Je suis d'accord avec matt b, peut-être ses espaces entre les balises JSP.Essayez de mettre la directive

<%@ page trimDirectiveWhitespaces="true" %> 
+0

trimDirectiveWhitespaces semble très utile, bien que certains googling révèle que c'est seulement depuis JSP 2.1 (donc c'est assez nouveau). –

4

Ok, j'ai eu ce travail. Voici comment je l'ai fait:

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); 
%> 

méthode 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()); 
     } 
    } 
} 

Merci à tous pour leur entrée!