How to convert iTextPDF Document to Byte Array

2019-02-13 19:31发布

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


}

2条回答
Viruses.
2楼-- · 2019-02-13 20:06

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

查看更多
贼婆χ
3楼-- · 2019-02-13 20:17

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.

查看更多
登录 后发表回答