Как преобразовать документ iTextPDF в байтовый массив

Мне нужно преобразовать файл iTextPDF Document в byte[] после его создания в памяти. Я уже проверил, что у меня нет проблем с правильным созданием PDF. Проблема в том, как преобразовать его в массив байтов для хранения в БД.

Вот мой код:

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

Я получил значение null в столбце базы данных blob.

Вот мой объект домена документа:

Объект домена документа

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


}

person talha06    schedule 10.08.2012    source источник
comment
посмотри на вопрос, потом посмотри на свое последнее предложение..   -  person Eugene    schedule 10.08.2012
comment
похоже, что документ не будет создан сначала из-за этой ошибки базы данных.   -  person Marvin Emil Brach    schedule 10.08.2012
comment
@ Юджин, это то же самое; Я сохраняю byte[] в столбец blob.   -  person talha06    schedule 10.08.2012
comment
@MarvinEmilBrach да, документ создается во время выполнения.   -  person talha06    schedule 10.08.2012
comment
@ talha06 Я все еще в замешательстве, можете ли вы подтвердить, что я правильно понимаю? Вы создаете PDF-документ динамически во время выполнения, а затем сохраняете его в БД в виде массива байтов? Если это правда, то в чем именно заключается ваш вопрос? Вы получаете нулевое значение при вставке в БД?   -  person Eugene    schedule 10.08.2012
comment
@Eugene, да, мне нужно правильно преобразовать документ iTextPDF в byte[]. Как я упоминал во фрагменте кода выше, переменная generatedDocument содержит только что сгенерированный PDF-документ. Затем мне нужно преобразовать его в массив байтов, чтобы сохранить базу данных. Спасибо за твою заботу.   -  person talha06    schedule 10.08.2012
comment
@ talha06 Я попробую это сам примерно через 1 час и вернусь к вам.   -  person Eugene    schedule 10.08.2012
comment
вы уверены, что генерация удалась? похоже, что outputstream вообще не получает никаких данных... Мне очень интересно, что Евгений расскажет в нашем :)   -  person Marvin Emil Brach    schedule 10.08.2012
comment
@MarvinEmilBrach да, генерация прошла успешно, я проверил ее, отправив сгенерированный PDF-файл клиенту. Еще раз спасибо Евгений за вашу заботу и время ..   -  person talha06    schedule 10.08.2012
comment
@MarvinEmilBrach правда :) делал три дела одновременно..   -  person Eugene    schedule 10.08.2012
comment
@Eugene Я создаю файл PDF только для тестирования. Обычно я создаю его во время выполнения, а затем сохраняю в БД. У меня уже есть фрагмент почтового кода, связанный с ним.   -  person talha06    schedule 10.08.2012


Ответы (3)


У меня была похожая проблема... Я создавал документ и внутри класса, в котором я его создал, я мог сохранить его в файл, и он отлично работал. Однако, когда я пытался вернуть его как поток, я получал нулевое значение.

Проблема заключалась в том, что после закрытия документа (document.close()) закрывался и поток.

Обходной путь заключался в том, чтобы создать ByteArrayOutputStream, когда я создал документ, и получить для него вывод PdfWriter. Затем я мог делать все, что хотел, с байтами PDF... в моем случае я преобразовал их в StreamedContent для отправки пользователю.

Создайте переменную для хранения байтов:

  private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

Пусть PdfWriter выводит данные в byte[] при создании документа:

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

Как только вы закончите создание PDF-файла, просто получите байты и делайте с ними, что хотите.

  byte[] pdfBytes = byteArrayOutputStream.toByteArray();

Я не знаю, как выглядит ваш класс reportService, но это может быть хорошим местом для его размещения.

Надеюсь это поможет.

person AceFunk    schedule 09.10.2013
comment
Отличный ответ! Мне очень помог! Есть ли какой-нибудь элегантный способ установить имя файла? Chrome загружает его как something.pdf автоматически. - person Djordje Ivanovic; 08.04.2014
comment
Спасибо! это было полезно, счастливого кодирования! - person Spartan; 27.05.2021

Из комментариев видно, что он не имеет ничего общего с тем, как PDF создается во время выполнения, а с тем, как он хранится в БД. Вам также необходимо предоставить этот код.

Вот что у меня есть на самом деле (мой тест):

Держатель:

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

Репозиторий, который делает сохранение:

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

И собственно вставка:

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

Конечно, у меня есть репозиторий @Autowired в этом классе:

@Autowired
PDFHolderRepository pdfHolderRepository;

MySQL сохраняет массив байтов

person Eugene    schedule 10.08.2012
comment
Я получаю null, когда извлекаю документ из БД. (Также я вижу ноль, когда в GUI - MySQL Workbench) Я сохраняю PDF в БД, используя Hibernate. Когда я отлаживаю код, я вижу, что документ успешно сгенерирован. Поэтому я хочу узнать, как я могу успешно преобразовать документ iTextPDF в массив байтов, чтобы сохранить его правильно. - person talha06; 10.08.2012
comment
@ talha06 см. мой обновленный ответ - я проверил это, и это работает. Также вы можете взглянуть на это: meta.stackexchange.com/questions/5234/ - person Eugene; 10.08.2012

Просто обновляю ответ для версии iText 7.

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();
}
person Guilherme Gehling    schedule 06.05.2021