2012-01-18 42 views
14

¿Cómo puedo hacer que un archivo PDF se descargue en un enlace?¿Cómo generar un PDF descargable con pdfbox (PDF dañado)?

Estoy construyendo una aplicación web usando JSF, cuando el usuario hace clic en el enlace "Guardar como PDF", debe estar disponible para descargar un PDF.

Hasta ahora tengo un código de trabajo que genera el archivo PDF, pero el archivo se guarda en mi escritorio y lo que quiero hacer es que cuando el usuario haga clic en el enlace, el archivo pdf se pueda descargar en lugar de ser almacenado en la aplicación.

Actualización 3: Gracias por su ayuda chicos, me modifed mi código con sus sugerencias y que está funcionando.

ACTUALIZACIÓN 2: Estoy recibiendo el siguiente error: Adoble Reader no se pudo abrir "yourfile.pdf" porque o bien no es un tipo de archivo compatible o porque el archivo se ha dañado

ACTUALIZACIÓN 1: estoy añadiendo mi código actual con los cambios que me han señalado, sin embargo, todavía estoy luchando para hacer este trabajo

This is my method that generated the PDF:

public ByteArrayOutputStream createPDF() throws IOException, COSVisitorException { 

    PDDocument document; 
    PDPage page; 
    PDFont font; 
    PDPageContentStream contentStream; 
    PDJpeg front; 
    PDJpeg back; 

    InputStream inputFront; 
    InputStream inputBack; 
    ByteArrayOutputStream output = new ByteArrayOutputStream(); 

    // Creating Document 
    document = new PDDocument(); 

    // Creating Pages 
    for(int i=0; i<2; i++) { 

     page = new PDPage(); 

     // Adding page to document 
     document.addPage(page); 

     // Adding FONT to document 
     font = PDType1Font.HELVETICA;   

     // Retrieve Image to be added to the PDF 
     inputFront = new FileInputStream(new File("D:/Media/imageFront.jpg")); 
     inputBack = new FileInputStream(new File("D:/Media/imageBack.jpg")); 

     BufferedImage buffFront = ImageIO.read(inputFront); 
     BufferedImage resizedFront = Scalr.resize(buffFront, 460); 

     BufferedImage buffBack = ImageIO.read(inputBack); 
     BufferedImage resizedBack = Scalr.resize(buffBack, 460); 

     front = new PDJpeg(document, resizedFront); 
     back = new PDJpeg(document, resizedBack); 

     // Next we start a new content stream which will "hold" the to be created content. 
     contentStream = new PDPageContentStream(document, page);     

     // Let's define the content stream 
     contentStream.beginText(); 
     contentStream.setFont(font, 8); 
     contentStream.moveTextPositionByAmount(10, 770); 
     contentStream.drawString("Amount: $1.00"); 
     contentStream.endText(); 

     contentStream.beginText(); 
     contentStream.setFont(font, 8); 
     contentStream.moveTextPositionByAmount(200, 770); 
     contentStream.drawString("Sequence Number: 123456789"); 
     contentStream.endText(); 

     contentStream.beginText(); 
     contentStream.setFont(font, 8); 
     contentStream.moveTextPositionByAmount(10, 760); 
     contentStream.drawString("Account: 123456789"); 
     contentStream.endText(); 

     contentStream.beginText(); 
     contentStream.setFont(font, 8); 
     contentStream.moveTextPositionByAmount(200, 760); 
     contentStream.drawString("Captura Date: 04/25/2011"); 
     contentStream.endText(); 

     contentStream.beginText(); 
     contentStream.setFont(font, 8); 
     contentStream.moveTextPositionByAmount(10, 750); 
     contentStream.drawString("Bank Number: 123456789"); 
     contentStream.endText(); 

     contentStream.beginText(); 
     contentStream.setFont(font, 8); 
     contentStream.moveTextPositionByAmount(200, 750); 
     contentStream.drawString("Check Number: 123456789"); 
     contentStream.endText();    

     // Let's close the content stream  
     contentStream.close(); 

    } 

    // Finally Let's save the PDF 
    document.save(output); 
    document.close(); 

    return output; 
} 

This is my servlet that call the previous code and generates the output and set the header:

try { 

     ByteArrayOutputStream output = new ByteArrayOutputStream(); 
     output = createPDF(); 

     response.addHeader("Content-Type", "application/force-download"); 
     response.addHeader("Content-Disposition", "attachment; filename=\"yourFile.pdf\""); 
     response.getOutputStream().write(output.toByteArray()); 

    } catch (Exception ex) {    
     ex.printStackTrace(); 
    } 

no estoy seguro de lo que me falta ya que cuando intento abrir el PDF Tengo el error: Adoble Reader no se pudo abrir "yourfile.pdf" porque o bien no es una tipo de archivo compatible o porque el archivo se ha dañado

+0

Re "Actualización 2", este podría ser este error: http://issues.apache.org/jira/browse/PDFBOX-2026. Será arreglado en 1.8.5. O descarga una instantánea. –

+0

Hola @Noche. Estoy tratando de implementar algo similar a lo que lograste. ¿Podría poner la declaración del objeto de respuesta dentro de su servlet? ¿O tal vez publicar el código completo? – Erick

Respuesta

7

Debe configurar los encabezados http adecuados para indicarle al navegador que descargue el archivo.

response.addHeader("Content-Type", "application/force-download") 
response.addHeader("Content-Disposition", "attachment; filename=\"yourFile.pdf\"") 
+0

Agregué un código de muestra a mi pregunta, también agregué los encabezados, pero recibí el siguiente error al intentar abrir el archivo PDF: Adoble Reader no pudo abrir "yourfile.pdf" porque no es un tipo de archivo compatible o porque el archivo ha sido dañado. –

+0

El "yourfile.pdf "debe ser un nombre de archivo que está generando. Solo lo incluí como nombre de muestra. Trate de eliminar las barras invertidas y las comillas. – jloper3

+0

response.addHeader (" Content-Disposition "," attachment; filename = yourFile.pdf ") – jloper3

4

No he hecho esto por un tiempo, así que tengan paciencia, pero lo que hacen es guardar el pdf en un archivo a través de una secuencia, guardar la secuencia en la memoria como una matriz de bytes y luego, cuando el usuario hace clic en el enlace, configura el tipo MIME en PDF y luego abre la matriz de bytes como una secuencia que usted devuelve como el esponja Me disculpo por ser un poco confuso en los detalles. Creo que también usé jpedal e iText para hacerlo.

No puedo mostrar todo el código, pero aquí es un poco de:

import com.itextpdf.text.BaseColor; 
import com.itextpdf.text.Document; 
import com.itextpdf.text.DocumentException; 
import com.itextpdf.text.Paragraph; 
import com.itextpdf.text.Phrase; 
import com.itextpdf.text.pdf.PdfPCell; 
import com.itextpdf.text.pdf.PdfPTable; 
import com.itextpdf.text.pdf.PdfWriter; 
import com.itextpdf.text.pdf.draw.DottedLineSeparator; 

... // class, etc. 

public ByteArrayOutputStream createOrderFormPdf(OrderFormDTO dto) 
     throws DocumentException { 
    Document document = new Document(); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    PdfWriter.getInstance(document, baos); 
    document.open(); 

    Paragraph header = new Paragraph(); 
    header.add(new Phrase(...)); 

    OrderFormDtoPdfAdapter pdfAdapter = new OrderFormDtoPdfAdapter(dto); 
    header.add(pdfAdapter.getPdfHeaderTable()); 

    document.add(header); 

      ... // other code 

    Paragraph footer = new Paragraph(); 
    footer.add(pdfAdapter.getPDFFooterTable()); 

    document.add(footer); 
    Paragraph paragraph = new Paragraph(); 
    PdfTableUtils.addEmptyLine(paragraph, 2); 

    document.add(paragraph); 
    document.add(new DottedLineSeparator()); 

    document.close(); 

    return baos; 
} 

A continuación, puede escribir los baos de su respuesta en formato PDF utilizando el tipo MIME correcto.

+0

Actualicé mi pregunta con una versión modificada de mi código en función de su respuesta. –

Cuestiones relacionadas