PDF Blocks
PreciosSoporte
Empezar gratis
Ir a la página

Encadenar acciones

Cómo pasar la salida de una acción directamente a la siguiente, con un pipeline de tres etapas resuelto y los casos en los que encadenar no es la herramienta adecuada.

Toda acción recibe un PDF y devuelve un PDF, así que la salida de una acción es una entrada válida para la siguiente. Eso le permite construir un pipeline de varios pasos con acciones de un solo propósito: unir unos archivos, estampar una marca de agua en el resultado y después cifrarlo, todo en un mismo script, pasando los bytes de una llamada a otra en memoria.

Como la API es stateless (no se almacena nada entre solicitudes), no hay ningún identificador que reutilizar ni nada que limpiar. Cada etapa simplemente entrega el cuerpo de su respuesta a la etapa siguiente como el campo file.

Cómo funciona

Una acción de salida única responde con 200 OK y Content-Type: application/pdf. El cuerpo es un PDF completo. Para encadenar, tome ese cuerpo y envíelo como la parte file de la solicitud siguiente en lugar de leer un archivo del disco. Solo la primera entrada y la última salida necesitan tocar el sistema de archivos; todo lo intermedio se queda en memoria.

Un pipeline de tres etapas

Este ejemplo convierte dos archivos de origen en un solo documento cifrado y con marca de agua.

Una los archivos de origen

POST /v1/merge_documents con cover.pdf y report.pdf devuelve un único PDF combinado. Consulte Unir documentos PDF para ver las opciones de entrada.

Estampe la marca de agua en los bytes unidos

Envíe ese PDF como el campo file a POST /v1/add_text_watermark. La respuesta es el mismo documento con una marca de agua en todas las páginas.

Cifre los bytes con marca de agua

Envíe el PDF con la marca de agua a POST /v1/add_password con una password. La respuesta es el documento final ya protegido: escríbalo en disco.

Unir acepta los PDF de entrada como partes file repetidas o, donde repetir un nombre de campo resulta incómodo (PHP, Ruby), como campos numerados de file_1 a file_10. A continuación se muestran ambas formas; use file repetido cuando tenga más de diez.

cURLbash
# Each stage reads the previous PDF from stdin via `-F 'file=@-'`.
curl -sS https://api.pdfblocks.com/v1/merge_documents \
  -H 'X-API-Key: your_api_key' \
  -F file=@cover.pdf \
  -F file=@report.pdf |
curl -sS https://api.pdfblocks.com/v1/add_text_watermark \
  -H 'X-API-Key: your_api_key' \
  -F 'file=@-;filename=merged.pdf;type=application/pdf' \
  -F line_1='CONFIDENTIAL' \
  -F line_2='ACME, Inc.' |
curl -sS https://api.pdfblocks.com/v1/add_password \
  -H 'X-API-Key: your_api_key' \
  -F 'file=@-;filename=watermarked.pdf;type=application/pdf' \
  -F password='pa$$word' \
  -o final.pdf
Pythonpython
# pip install requests
import requests

BASE = 'https://api.pdfblocks.com'
HEADERS = {'X-API-Key': 'your_api_key'}

# 1. Merge cover.pdf and report.pdf into one document.
with open('cover.pdf', 'rb') as cover, open('report.pdf', 'rb') as report:
    merged = requests.post(
        f'{BASE}/v1/merge_documents',
        headers=HEADERS,
        files=[('file', cover), ('file', report)],
    )
merged.raise_for_status()

# 2. Watermark the merged bytes: no temp file.
watermarked = requests.post(
    f'{BASE}/v1/add_text_watermark',
    headers=HEADERS,
    files={'file': ('merged.pdf', merged.content, 'application/pdf')},
    data={'line_1': 'CONFIDENTIAL', 'line_2': 'ACME, Inc.'},
)
watermarked.raise_for_status()

# 3. Encrypt the watermarked bytes.
final = requests.post(
    f'{BASE}/v1/add_password',
    headers=HEADERS,
    files={'file': ('watermarked.pdf', watermarked.content, 'application/pdf')},
    data={'password': 'pa$$word'},
)
final.raise_for_status()

with open('final.pdf', 'wb') as output:
    output.write(final.content)
Node.jsjavascript
// Node.js 18+
import { readFile, writeFile } from 'node:fs/promises';

const BASE = 'https://api.pdfblocks.com';
const headers = { 'X-API-Key': 'your_api_key' };

// Post a multipart form and return the response PDF as bytes.
async function post(path, form) {
  const response = await fetch(BASE + path, { method: 'POST', headers, body: form });
  if (!response.ok) throw new Error(`${path} failed: ${response.status}`);
  return new Uint8Array(await response.arrayBuffer());
}

// 1. Merge cover.pdf and report.pdf.
const mergeForm = new FormData();
mergeForm.append('file', new Blob([await readFile('cover.pdf')]), 'cover.pdf');
mergeForm.append('file', new Blob([await readFile('report.pdf')]), 'report.pdf');
const merged = await post('/v1/merge_documents', mergeForm);

// 2. Watermark the merged bytes.
const watermarkForm = new FormData();
watermarkForm.append('file', new Blob([merged]), 'merged.pdf');
watermarkForm.append('line_1', 'CONFIDENTIAL');
watermarkForm.append('line_2', 'ACME, Inc.');
const watermarked = await post('/v1/add_text_watermark', watermarkForm);

// 3. Encrypt the watermarked bytes.
const passwordForm = new FormData();
passwordForm.append('file', new Blob([watermarked]), 'watermarked.pdf');
passwordForm.append('password', 'pa$$word');
const final = await post('/v1/add_password', passwordForm);

await writeFile('final.pdf', final);
PHPphp
<?php
$base = 'https://api.pdfblocks.com';
$headers = ['X-API-Key: your_api_key'];

// Post a multipart form and return the response body, or throw on error.
function post(string $url, array $headers, array $fields): string {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $fields,
    ]);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($status !== 200) {
        throw new RuntimeException("Request to $url failed with status $status.");
    }
    return $body;
}

// 1. Merge cover.pdf and report.pdf (numbered fields for the array input).
$merged = post("$base/v1/merge_documents", $headers, [
    'file_1' => new CURLFile('cover.pdf', 'application/pdf'),
    'file_2' => new CURLFile('report.pdf', 'application/pdf'),
]);

// 2. Watermark the merged bytes in memory (CURLStringFile, PHP 8.1+).
$watermarked = post("$base/v1/add_text_watermark", $headers, [
    'file' => new CURLStringFile($merged, 'merged.pdf', 'application/pdf'),
    'line_1' => 'CONFIDENTIAL',
    'line_2' => 'ACME, Inc.',
]);

// 3. Encrypt the watermarked bytes.
$final = post("$base/v1/add_password", $headers, [
    'file' => new CURLStringFile($watermarked, 'watermarked.pdf', 'application/pdf'),
    'password' => 'pa$$word',
]);

file_put_contents('final.pdf', $final);
Rubyruby
# gem install http
require 'http'
require 'stringio'

BASE = 'https://api.pdfblocks.com'
HEADERS = { 'X-API-Key' => 'your_api_key' }

def post(path, fields)
  response = HTTP.headers(HEADERS).post("#{BASE}#{path}", form: fields)
  raise "#{path} failed: #{response.status}" unless response.status.success?
  response.body.to_s
end

# 1. Merge cover.pdf and report.pdf (numbered fields for the array input).
merged = post('/v1/merge_documents',
  file_1: HTTP::FormData::File.new('cover.pdf'),
  file_2: HTTP::FormData::File.new('report.pdf'))

# 2. Watermark the merged bytes in memory.
watermarked = post('/v1/add_text_watermark',
  file: HTTP::FormData::File.new(StringIO.new(merged),
    filename: 'merged.pdf', content_type: 'application/pdf'),
  line_1: 'CONFIDENTIAL',
  line_2: 'ACME, Inc.')

# 3. Encrypt the watermarked bytes.
final = post('/v1/add_password',
  file: HTTP::FormData::File.new(StringIO.new(watermarked),
    filename: 'watermarked.pdf', content_type: 'application/pdf'),
  password: 'pa$$word')

File.write('final.pdf', final)
Gogo
package main

import (
	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

const base = "https://api.pdfblocks.com"

// post sends a multipart form and returns the response PDF bytes.
func post(path string, build func(*multipart.Writer)) []byte {
	var buf bytes.Buffer
	form := multipart.NewWriter(&buf)
	build(form)
	form.Close()

	req, _ := http.NewRequest("POST", base+path, &buf)
	req.Header.Set("Content-Type", form.FormDataContentType())
	req.Header.Set("X-API-Key", "your_api_key")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	body, _ := io.ReadAll(res.Body)
	if res.StatusCode != http.StatusOK {
		panic(fmt.Sprintf("%s failed: %d", path, res.StatusCode))
	}
	return body
}

func addFile(form *multipart.Writer, name string, data []byte) {
	part, _ := form.CreateFormFile("file", name)
	part.Write(data)
}

func main() {
	cover, _ := os.ReadFile("cover.pdf")
	report, _ := os.ReadFile("report.pdf")

	// 1. Merge cover.pdf and report.pdf.
	merged := post("/v1/merge_documents", func(form *multipart.Writer) {
		addFile(form, "cover.pdf", cover)
		addFile(form, "report.pdf", report)
	})

	// 2. Watermark the merged bytes.
	watermarked := post("/v1/add_text_watermark", func(form *multipart.Writer) {
		addFile(form, "merged.pdf", merged)
		form.WriteField("line_1", "CONFIDENTIAL")
		form.WriteField("line_2", "ACME, Inc.")
	})

	// 3. Encrypt the watermarked bytes.
	final := post("/v1/add_password", func(form *multipart.Writer) {
		addFile(form, "watermarked.pdf", watermarked)
		form.WriteField("password", "pa$$word")
	})

	os.WriteFile("final.pdf", final, 0644)
}
C#csharp
using System.Net.Http.Headers;

const string Base = "https://api.pdfblocks.com";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "your_api_key");

// Post a multipart form and return the response PDF bytes.
async Task<byte[]> Post(string path, Action<MultipartFormDataContent> build)
{
    using var form = new MultipartFormDataContent();
    build(form);
    var response = await client.PostAsync(Base + path, form);
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadAsByteArrayAsync();
}

static void AddFile(MultipartFormDataContent form, string name, byte[] data)
{
    var content = new ByteArrayContent(data);
    content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
    form.Add(content, "file", name);
}

// 1. Merge cover.pdf and report.pdf.
var merged = await Post("/v1/merge_documents", form =>
{
    AddFile(form, "cover.pdf", File.ReadAllBytes("cover.pdf"));
    AddFile(form, "report.pdf", File.ReadAllBytes("report.pdf"));
});

// 2. Watermark the merged bytes.
var watermarked = await Post("/v1/add_text_watermark", form =>
{
    AddFile(form, "merged.pdf", merged);
    form.Add(new StringContent("CONFIDENTIAL"), "line_1");
    form.Add(new StringContent("ACME, Inc."), "line_2");
});

// 3. Encrypt the watermarked bytes.
var final = await Post("/v1/add_password", form =>
{
    AddFile(form, "watermarked.pdf", watermarked);
    form.Add(new StringContent("pa$$word"), "password");
});

await File.WriteAllBytesAsync("final.pdf", final);

Compruebe cada etapa antes de pasarla a la siguiente

Una etapa que falla devuelve un 4XX con un cuerpo application/problem+json, no un PDF. Si canaliza ese cuerpo de error a la solicitud siguiente como file, la etapa siguiente también fallará, con un mensaje confuso. Compruebe el estado de cada respuesta antes de pasar su cuerpo: los ejemplos anteriores lanzan un error ante cualquier respuesta que no sea 200. Consulte Errores para ver la forma de la respuesta.

Estampe la marca de agua y una los documentos antes de cifrar. Una vez que Añadir una contraseña ha cifrado un documento, las acciones posteriores no pueden abrirlo, así que cualquier paso de contraseña va al final del pipeline. Consulte Proteger y desbloquear documentos para ver todas las reglas de orden.

Cuándo encadenar y cuándo no

Encadene cuando cada paso sea una transformación distinta que quiera aplicar en secuencia. Mantenga cada paso como una llamada pura y de un solo propósito: eso es lo que hace que la salida de una sea una entrada válida para la siguiente, y lo que mantiene los fallos fáciles de localizar.

Algunas tareas parecen encadenamientos y no lo son. Reordenar y descartar páginas en una sola pasada es una única llamada a Reordenar páginas, no una extracción seguida de una unión. Recurra a un pipeline solo cuando ninguna acción por sí sola haga todo el trabajo.

Relacionado