How to convert iTextPDF Document to Byte Array
Asked Answered
D

3

16

I need to convert iTextPDF Document file to byte[] after it's created in memory. I have already tested that I've no problem with creating PDF properly. The problem is how to convert it to byte array to store in DB.

Here's my code:

Document generatedDocument = reportService.generateRequestForm(scdUser, jsonObject, 0, null);
reportService.generateRequestForm(scdUser, jsonObject, 0, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter pdfWriter = PdfWriter.getInstance(generatedDocument, baos);
generatedDocument.open();
document.setDocument(baos.toByteArray()); // stores as blob

I got value of null at database blob column.

Here's my Document domain object:

Document Domain Object

@Entity
@Table(name = "document")
public class Document implements java.io.Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "document_id", nullable = false)
    private int documentId;
    @Column(name = "document_name", nullable = false, length = 65535)
    private String documentName;
    @Column(name = "document_type", nullable = false)
    private int documentType;
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "upload_date", nullable = false, length = 19)
    private Date uploadDate = new Date();
    @Column(name = "document", nullable = false)
    private byte[] document;    // BLOB COLUMN
    @Column(name = "document_size", nullable = false)
    private long documentSize;
    @Column(name = "title", nullable = true, insertable = true, updatable = true, length = 65535, precision = 0)
    private String title;
    @Column(name = "tag", nullable = true, insertable = true, updatable = true, length = 65535, precision = 0)
    private String tag;
    @Column(name = "description", nullable = true, insertable = true, updatable = true, length = 65535, precision = 0)
    private String description;
    @Column(name = "shared", nullable = false, insertable = true, updatable = true, length = 1, precision = 0)
    private boolean shared = false;
    @Column(name = "status", nullable = false)
    private int status = DocumentStatus.READY.getStatus();


    public int getDocumentId() {
        return this.documentId;
    }

    public void setDocumentId(int documentId) {
        this.documentId = documentId;
    }

    public String getDocumentName() {
        return this.documentName;
    }

    public void setDocumentName(String documentName) {
        this.documentName = documentName;
    }

    public int getDocumentType() {
        return this.documentType;
    }

    public void setDocumentType(int documentType) {
        this.documentType = documentType;
    }

    public Date getUploadDate() {
        return this.uploadDate;
    }

    public void setUploadDate(Date uploadDate) {
        this.uploadDate = uploadDate;
    }

    public byte[] getDocument() {
        return this.document;
    }

    public void setDocument(byte[] document) {
        this.document = document;
    }

    public long getDocumentSize() {
        return this.documentSize;
    }

    public void setDocumentSize(long documentSize) {
        this.documentSize = documentSize;
    }

    public String getTag() {
        return tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public boolean getShared() {
        return shared;
    }

    public void setShared(boolean shared) {
        this.shared = shared;
    }


    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }


}
Delaney answered 10/8, 2012 at 7:32 Comment(11)
look at the question, then look at your last sentence..Aman
looks like the document will not be generated at first in cause of that database error.Krongold
@Aman it's same; I'm persisting byte[] to blob column.Delaney
@MarvinEmilBrach yeah the document is generated at runtime.Delaney
@Delaney I am still confused, can you confirm that my understanding is right? You create a PDF document dynamically at runtime, then store it in the DB as byte array? If true, then what is your question exactly? You get a null value when inserting in the DB?Aman
@Aman yeah exactly I need to convert iTextPDF Document to byte[] properly. As I mentioned in code snippet above, the variable generatedDocument holds PDF document that is just generated. Then I need to convert it to byte array to persist db. Thanks for your care.Delaney
@Delaney I will try this myself in about 1 hour and get back to youAman
are you sure that the generation was successful? seems like the outputstream doesn't receive any data at all... I'm really curious what Eugene will tell in an our :)Krongold
@MarvinEmilBrach yeah generation is successful, I tested it with sending generated PDF to client. Thanks again Eugene for your care & time..Delaney
@MarvinEmilBrach true :) was doing three things at once..Aman
@Aman I create PDF file just for testing. Normally I'll create it at runtime, then I'll persist it to DB. I have already post code snippet that is associated with it..Delaney
I
30

I had a similar problem... I'd create the Document and inside the class where I created it, I could save it to File, and it worked great. However, when I tried to return it as a Stream I would get a null value.

The problem was that once the Document was closed (document.close()), it would close the Stream also.

The work-around was to create a ByteArrayOutputStream when I created the Document and have the PdfWriter output to it. I could then do whatever I wanted with the PDF bytes... in my case I converted them to a StreamedContent to send to the user.

Create a variable to hold the bytes:

  private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

Have the PdfWriter output the data to the byte[] as it creates the document:

  Document document = new Document(PageSize.LETTER, 0.75F, 0.75F, 0.75F, 0.75F);
  PdfWriter.getInstance(document, byteArrayOutputStream);  // Do this BEFORE document.open()

  document.open();
  createPDF(document);  // Whatever function that you use to create your PDF
  document.close();

Once you're done generating the PDF, just get the Bytes and do with them as you will.

  byte[] pdfBytes = byteArrayOutputStream.toByteArray();

I don't know what your reportService class looks like, but this may be a good place to put it.

Hope this helps.

Infelicitous answered 9/10, 2013 at 14:17 Comment(2)
Great answer! Helped me a lot! Is there some elegant way to set the name of the file? Chrome downloads it as "something.pdf" automatically.Picro
Thanks! this was helpful, happy coding!Presidency
R
8

Just updating the answer for the iText 7 version.

private static byte[] createPDF() {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    PdfWriter writer = new PdfWriter(byteArrayOutputStream);
    PdfDocument pdfDocument = new PdfDocument(writer);
    Document document = new Document(pdfDocument);

    //Write the file content

    document.close();
    return byteArrayOutputStream.toByteArray();
}
Reproachless answered 6/5, 2021 at 3:58 Comment(0)
A
2

From the comments it appears that it has nothing to do the way PDF is generated at runtime, but instead the way it is stored in the DB. You need to provide that code also.

Here is what I have actually (my test):

The Holder:

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;



@Entity
public class PDFHolder implements Serializable {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long id;

@Column(columnDefinition = "LONGBLOB")
private byte[] documentPDF;

public byte[] getDocumentPDF() {
    return documentPDF;
}

public void setDocumentPDF(byte[] documentPDF) {
    this.documentPDF = documentPDF;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}
}

The Repository, which does the save:

@Repository
public interface PDFHolderRepository extends JpaRepository<PDFHolder, Long> {}

And the actual insert:

private void generateDatabaseRows() {

    try{
        String urlPDF = "http://cetatenie.just.ro/LinkClick.aspx?fileticket=K13DZkoIE2o%3d&tabid=57&mid=593";
        URL url = new URL(urlPDF);

        ByteBuffer byteBufferResponse = this.getAsByteArray(url.openConnection());
        byte [] responseArray = byteBufferResponse.array();
        System.out.println("Size of the PDF : " + responseArray.length);

        // Save it to DB
        PDFHolder pdfHolder = new PDFHolder();
        pdfHolder.setDocumentPDF(responseArray);

        pdfHolderRepository.save(pdfHolder);

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


private ByteBuffer getAsByteArray(final URLConnection urlConnection) throws IOException {
    final ByteArrayOutputStream tmpOut = new ByteArrayOutputStream();
    final InputStream inputStream = urlConnection.getInputStream();
    final byte[] buf = new byte[1024];
    int len;
    while (true) {
        len = inputStream.read(buf);
        if (len == -1) {
            break;
        }
        tmpOut.write(buf, 0, len);
    }
    tmpOut.close();
    return ByteBuffer.wrap(tmpOut.toByteArray(), 0, tmpOut.size());
}

Of course I have an @Autowired repository in this class:

@Autowired
PDFHolderRepository pdfHolderRepository;

MySQL stores the byte array

Aman answered 10/8, 2012 at 10:8 Comment(2)
I get null when I retrieve document from DB. (Also I see null when at GUI - MySQL Workbench) I persist PDF to DB using Hibernate. When I debug the code, I see the document is generated successfully. So I want to learn how can I successfully convert iTextPDF Document to byte array in order to persist properly.Delaney
@Delaney see my updated answer - I've tested this and it works. Also you might want to have a look at this: meta.stackexchange.com/questions/5234/…Aman

© 2022 - 2024 — McMap. All rights reserved.