18

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;
    }


}
11
  • look at the question, then look at your last sentence.. Commented Aug 10, 2012 at 7:40
  • looks like the document will not be generated at first in cause of that database error. Commented Aug 10, 2012 at 7:51
  • @Eugene it's same; I'm persisting byte[] to blob column. Commented Aug 10, 2012 at 8:03
  • @MarvinEmilBrach yeah the document is generated at runtime. Commented Aug 10, 2012 at 8:04
  • 1
    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 :) Commented Aug 10, 2012 at 8:44

3 Answers 3

32

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.

Sign up to request clarification or add additional context in comments.

1 Comment

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.
9

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

Comments

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

2 Comments

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.
@talha06 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/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.