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.