Enviar un PDF desde tu ordenador a una impresora remota

En este tutorial, te muestro cómo crear una página web que envíe un archivo PDF desde tu ordenador a una impresora remota mediante el servicio Expedy Print.

El ejemplo utiliza una impresora de etiquetas para imprimir etiquetas de envío adhesivas en el formato estándar 4×6 (10×15 cm), por ejemplo, etiquetas generadas desde una tienda online, enviadas a una impresora situada en otra zona del almacén o en casa de un socio de dropshipping al otro lado del mundo.

El formulario también incluye un campo de texto para generar un PDF al vuelo. Ambas funciones (carga de archivos y texto a PDF) pueden usarse de forma independiente o conjunta.

Código fuente completo: github.com/ExpedyDev/pdftoprinter


Requisitos

Hardware

  • Una impresora térmica (este ejemplo usa una Netum NT-LP110F, pero los modelos Zebra, Brother, BeePRT y otros son compatibles, incluidos los formatos A3/A4/foto)
  • Un adaptador Expedy Cloud Print
  • Una conexión a internet estándar

Web

  • Librería FPDF
  • Librería FPDI
  • Una cuenta activa en Expedy Print
  • API ExpedyPrint V2

1. Creación del formulario HTML

El formulario incluye dos campos:

  • Un campo de texto para generar un PDF al vuelo
  • Un selector de archivos para subir uno o varios archivos PDF existentes
<!DOCTYPE html>
<html>
<head>
  <title>Crear un PDF e imprimir</title>
</head>
<body>
  <h1>Crear un PDF e imprimir</h1>
  <form method="post" action="" enctype="multipart/form-data">
    <label for="text">Introduce el texto a imprimir como PDF:</label><br>
    <input type="text" id="text" name="text"><br><br>

    <label for="files">Subir archivos PDF:</label><br>
    <input type="file" id="files" name="files[]" multiple><br><br>

    <button type="submit" name="submit">Imprimir</button>
  </form>
</body>
</html>

2. Código PHP

Aquí está el código PHP completo con comentarios integrados:

<?php
if (isset($_POST['submit'])) {
    if (!empty($_POST['text']) || !empty($_FILES['files']['tmp_name'][0])) {

        $text    = $_POST['text'];
        $pdfName = "pdf_" . date('Ymd_His') . ".pdf";

        require('fpdf/fpdf.php');
        require('fpdi/src/autoload.php');

        // Formato 4×6 (105×148 mm)
        $pdf = new \setasign\Fpdi\Fpdi('P', 'mm', array(105, 148));

        // Fusionar los archivos PDF subidos
        if (!empty($_FILES['files']['tmp_name'][0])) {
            foreach ($_FILES['files']['tmp_name'] as $file) {
                if (!empty($file) && file_exists($file)) {
                    $pageCount = $pdf->setSourceFile($file);
                    for ($pageNumber = 1; $pageNumber <= $pageCount; $pageNumber++) {
                        $tplIdx = $pdf->importPage($pageNumber);
                        $pdf->AddPage();
                        $pdf->useTemplate($tplIdx);
                    }
                }
            }
        }

        // Añadir una página desde el campo de texto
        if (!empty($text)) {
            $pdf->AddPage();
            $pdf->SetFont('Arial', 'B', 16);
            $pdf->Cell(40, 10, $text);
        }

        $pdf->Output('F', $pdfName);

        $file_url = 'https://' . $_SERVER['HTTP_HOST'] . '/' . $pdfName;
        sendToExpedyPrinter($file_url);

        echo "<p>¡Sus archivos han sido enviados a la impresora!</p>";

    } else {
        echo "<p>No se ha especificado ningún texto ni archivo PDF.</p>";
    }
}

function sendToExpedyPrinter($file_url) {

    $printer_uid = 'INTRODUCIR_UID_IMPRESORA';

    $data = array(
        'usb_msg' => $file_url,
        'origin'  => 'Your defined origin tag.. a uri, a name ..'
    );

    $options = array(
        CURLOPT_URL            => "https://www.expedy.fr/api/v2/devices/" . $printer_uid . "/usb/4/print",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING       => "",
        CURLOPT_MAXREDIRS      => 10,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST  => "POST",
        CURLOPT_POSTFIELDS     => json_encode($data),
        CURLOPT_HTTPHEADER     => array(
            "Accept: application/json",
            "Authorization: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "Content-Type: application/json"
        ),
    );

    $curl = curl_init();
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    $err      = curl_error($curl);
    curl_close($curl);

    if ($err) {
        echo "cURL Error #: " . $err;
    } else {
        echo $response;
    }
}
?>

Puntos clave

Librerías FPDF y FPDI

Ambas librerías son necesarias: FPDF se encarga de la generación del PDF, mientras que FPDI fusiona varios archivos en un único documento. Este paso de fusión es importante, es más eficiente para la impresora recibir un solo PDF multipágina que varios archivos separados enviados uno a uno a la API.

Formato del texto generado

Si el campo de texto está relleno, se añade una página adicional al PDF generado. La fuente puede personalizarse aquí:

$pdf->SetFont('Arial', 'B', 16);

Dimensiones del PDF

Este ejemplo utiliza el formato 4×6 (105×148 mm) para etiquetas de envío. El ancho y el alto pueden ajustarse para adaptarse a cualquier formato de papel:

$pdf = new \setasign\Fpdi\Fpdi('P', 'mm', array(105, 148));

UID de la impresora

Obtén el identificador único de tu impresora en la consola Expedy, sección Printers. No incluyas el #. Ejemplo: GSEPOHGEIO.

$printer_uid = 'INTRODUCIR_UID_IMPRESORA';

Claves API

Disponibles en la consola Expedy, menú API Keys. Formato: sid:token.

"Authorization: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",

Puerto USB

En este ejemplo, la impresora está conectada al puerto USB número 4. Para identificar el puerto correcto, ve a la consola Expedy > Machines > USB SCAN.

CURLOPT_URL => "https://www.expedy.fr/api/v2/devices/" . $printer_uid . "/usb/4/print",

Probar una impresión

Si todo está configurado correctamente, se creará un archivo PDF en tu carpeta raíz y la API devolverá una respuesta de confirmación.

⚠️ Atención: los archivos PDF generados no se eliminan automáticamente. Con el tiempo, pueden ocupar un espacio considerable en el disco de tu servidor de alojamiento.