Creación de firmas visibles con la biblioteca Java de Apache PDFBox v2

Aprenda a agregar una imagen de firma estática codificada en base64 a un PDF con PDFBox, con un sistema de coordenadas que comienza en la parte inferior izquierda para una ubicación natural.

21 Aug
,
2023
24 Jun
,
2025
# min read
Diagrama que muestra las coordenadas del rectángulo PDF para la maquetación y el diseño de documentos digitales

Una de las funciones más comunes de las aplicaciones de firma de documentos es la posibilidad de mostrar un representación visual de la firma de un usuario—básicamente, una imagen— en el PDF final firmado.

En este artículo, veremos cómo lograrlo usando Caja PDF Apache y una imagen PNG codificada en base64. Este enfoque se basa en el oficial Caja PDF Crear firma visible 2 ejemplo, con algunas diferencias clave:

¿Qué hay de diferente en este enfoque?

  • Imagen estática: En lugar de generar la imagen de la firma de forma dinámica, utilizamos un PNG codificado en base64 pregenerado.
  • Sistema de coordenadas: Posicionamos la imagen partiendo del esquina inferior izquierda de la página, lo que es más intuitivo: la mayoría de las firmas aparecen en la parte inferior de los documentos.

Ejemplo completo de Java

A continuación se muestra un ejemplo práctico en el que se carga un PDF codificado en base64, se aplica una imagen de firma codificada en base64 en una posición determinada de la primera página y se prepara el documento para la firma:

public class VisualSigner {
    public void addVisibleSignatureToPdf() throws IOException {
        String pdfInBase64 = "JVBERi0xLjQKJdPr....jEwODg5CiUlRU9G";
        String signatureImageInBase64 = "iVBORw0KGgoAAAA...gAAAAASUVORK5CYII=";
        long signatureTime = 1692617329341L;

        PDDocument document = PDDocument.load(Base64.getDecoder().decode(pdfInBase64));
        PDSignature signature = new PDSignature();
        signature.setType(COSName.getPDFName("Sig"));
        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
        signature.setSubFilter(PDSignature.SUBFILTER_ETSI_CADES_DETACHED);

        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date(signatureTime));
        signature.setSignDate(cal);

        SignatureOptions options = new SignatureOptions();
        options.setPreferredSignatureSize(SignatureOptions.DEFAULT_SIGNATURE_SIZE);

        int pageNum = 0;
        options.setPage(pageNum);

        Rectangle2D rect = new Rectangle2D.Float(20, 10, 200, 100);
        PDRectangle pdfRect = createSignatureRectangle(document, rect);
        options.setVisualSignature(createVisualSignatureTemplate(document, pageNum, pdfRect, signatureImageInBase64));

        document.addSignature(signature, options);

        try (FileOutputStream output = new FileOutputStream("prepared.pdf")) {
            document.saveIncrementalForExternalSigning(output);
        }

        document.close();
        IOUtils.closeQuietly(options);
    }

    // (Helper methods continue below...)
}

Los métodos auxiliares Crear rectángulo de firma y Crear plantilla de firma visual gestionar la alineación de coordenadas y la representación de imágenes. (Consulte el código completo en el repositorio o más abajo).

Comprensión de las coordenadas de PDFBox

En Crear rectángulo de firma, colocamos el rectángulo usando:

rect.setLowerLeftX(...);
rect.setLowerLeftY(...);
rect.setUpperRightX(...);
rect.setUpperRightY(...);

Esto define el rectángulo en el que aparecerá la imagen de la firma. Así es como funciona visualmente:

(Inserte un diagrama que muestre el origen en la parte inferior izquierda, con flechas que muestren cómo las coordenadas definen un rectángulo).

  • Esquina inferior izquierda define el punto de partida (x, y)
  • Esquina superior derecha define el final (x + ancho, y + alto)

También se tiene en cuenta la rotación de la página, lo que garantiza que la firma siempre aparezca correctamente orientada.

¿Por qué usar una imagen codificada en Base64?

El uso de base64 permite flexibilidad en la forma en que se obtiene la imagen. Puedes:

  • Almacénelo en una base de datos
  • Intégralo en una carga útil de API
  • Genérelo en el cliente (por ejemplo, desde un lienzo) y páselo al backend

No se necesitan archivos temporales, basta con decodificarlos y aplicarlos directamente.

Reflexiones finales

Este método es útil cuando:

  • Necesitas un firma visual rápida y uniforme
  • no quiero generar el lado del servidor de imágenes cada vez
  • Necesitas vista previa o prueba firma de flujos antes de integrar operaciones criptográficas completas

También funciona muy bien con los flujos de firma externos, como cuando un proveedor de servicios de confianza remoto aplica la firma después de preparar la capa visual.

More latest articles

See all news
See all news