Almacena archivos subidos y resultados sin configurar un bucket
Conservar los archivos procesados suele implicar configurar el almacenamiento por separado: crear un bucket de S3, escribir una política de IAM y añadir credenciales a un Template. Es trabajo extra antes de llegar al problema que realmente querías resolver.
Transloadit Storage ofrece una alternativa para los Workspaces admitidos. El Robot /transloadit/store
guarda los archivos en el almacenamiento de tu Workspace, y una URL firmada de Smart CDN sirve el
original o un derivado generado al vuelo. La Biblioteca de archivos de la Console y un endpoint
compatible con S3 ofrecen formas de gestionar esos archivos cuando la Biblioteca de archivos está
habilitada para tu Workspace.
Transloadit Storage está en vista previa privada. Si quieres probarlo antes de su disponibilidad general, pregúntanos por el acceso para tu Workspace. Este tutorial también necesita acceso a la Biblioteca de archivos, que nuestro equipo habilita por separado. Habilitar Storage por sí solo no otorga ese acceso.
Este tutorial lleva un archivo de tu disco a Transloadit Storage y de vuelta hacia fuera a través de Smart CDN en cuatro pasos breves, con Node.js y el SDK oficial. En ningún momento se crea un bucket.
Lo que necesitas
- Node.js 22 o una versión posterior.
- Un Workspace admitido en la vista previa de Storage con acceso a la Biblioteca de archivos habilitado.
- Dos Auth Keys de Credenciales en la Console: una clave de API con
assemblies:write,dam:read,templates:readytemplates:writepara los ejemplos siguientes, y una clave de firma de Smart CDN aparte. Para esa segunda clave, elige Nueva Auth Key y Entrega privada de imágenes (firma de Smart CDN), que habilita Smart CDN y selecciona solosmart_cdn:sign. Para subir directamente a través de S3 también se necesitadam:write. - La AWS CLI para los comandos opcionales de S3 del paso 2.
- El slug de tu Workspace: la parte que sigue a
/c/en la URL de la Console, por ejemplo,mytransloadit-toystory-app.
Las Assemblies autorizadas por assemblies:write pueden almacenar e importar archivos mediante los Robots
de Storage. Los ámbitos dam:read y dam:write controlan el acceso directo a S3, no esas operaciones de
Assembly.
Habilitar Smart CDN en una clave no limita qué más puede hacer; eso lo determinan sus permisos. Con
solo smart_cdn:sign, la clave no puede crear Assemblies independientes ni gestionar Storage. Aun así,
cualquiera que tenga su Auth Secret puede firmar URL que ejecutan transformaciones en tu cuenta y
sirven tus archivos almacenados, así que guárdalo en tu servidor como cualquier otro Auth Secret. Si
se filtra, elimina la clave y crea una de reemplazo.
Crea un proyecto y un archivo .env:
mkdir zero-config-storage && cd zero-config-storage
npm init -y && npm pkg set type=module
npm install @transloadit/node @transloadit/utils
curl --fail --location --output photo.jpg https://demos.transloadit.com/inputs/chameleon.jpg
TRANSLOADIT_KEY=your-api-auth-key
TRANSLOADIT_SECRET=your-api-auth-secret
TRANSLOADIT_CDN_KEY=your-smart-cdn-auth-key
TRANSLOADIT_CDN_SECRET=your-smart-cdn-auth-secret
TRANSLOADIT_WORKSPACE=your-workspace-slug
Node lo lee con --env-file, así que no hay dependencia de dotenv. Para los comandos de shell del
paso 2, cárgalo con set -a; . ./.env; set +a y usa esa misma terminal. Durante la vista previa, es posible que
también hayas recibido de nuestra parte sustituciones de endpoints (TRANSLOADIT_ENDPOINT, TRANSLOADIT_STORAGE_S3_ENDPOINT,
TRANSLOADIT_SMART_CDN_BASE_URL, TRANSLOADIT_SMART_CDN_EXTRA_PARAMS); los scripts siguientes las usan cuando están presentes y, en
caso contrario, recurren a los valores predeterminados de producción. Pon entre comillas los valores
que contengan espacios o caracteres de shell como & en .env, para que el archivo también
pueda cargarse de forma segura con el comando de shell.
Paso 1: almacena un archivo con /transloadit/store
/transloadit/store es un Robot de almacenamiento como /s3/store, salvo que no necesita credenciales ni
bucket: escribe en el almacenamiento de tu Workspace. path indica dónde termina el archivo;
las carpetas se crean bajo demanda y ${file.name} se sustituye para cada archivo.
import { Transloadit } from '@transloadit/node'
const client = new Transloadit({
authKey: process.env.TRANSLOADIT_KEY,
authSecret: process.env.TRANSLOADIT_SECRET,
endpoint: process.env.TRANSLOADIT_ENDPOINT,
})
const assembly = await client.createAssembly({
files: { photo: './photo.jpg' },
params: {
steps: {
stored: {
robot: '/transloadit/store',
use: ':original',
path: 'uploads/${file.name}',
// Uploading the same name again creates a new version instead of failing.
conflict_strategy: 'overwrite',
},
},
},
waitForCompletion: true,
})
// Storing Robots do not add a result key of their own: they annotate the file they stored,
// which is still listed under the step that produced it — here the upload, `:original`.
const [stored] = assembly.results[':original']
console.log(`Stored ${stored.path} (${stored.size} bytes, asset ${stored.asset_id})`)
node --env-file=.env store.js
# Stored uploads/photo.jpg (9309370 bytes, asset 8kLg…)
Esa es toda la parte de «configurar el almacenamiento» de este tutorial. El archivo ahora está en
uploads/photo.jpg dentro de tu Workspace. Si vuelves a almacenar en la misma ruta, obtienes una nueva
versión (conflict_strategy: 'overwrite'). Puedes recuperar una versión anterior mientras se conserve; el versionado
no es una promesa de conservación permanente ni un sustituto de tu política de copias de seguridad.
Paso 2: visualízalo en la Console o con las herramientas de S3 que ya tienes
Nuestro equipo debe habilitar la Biblioteca de archivos para tu Workspace. Después, el propietario, un administrador o un miembro normal del Workspace puede abrirla; un administrador de facturación no puede. Habilitar Storage por sí solo no desbloquea la página ni su endpoint de S3.
Una vez habilitado el acceso, abre la Console, elige tu Workspace y ve a
Biblioteca de archivos (https://transloadit.com/c/<workspace-slug>/file-library/). Ahí está la carpeta uploads con
photo.jpg dentro. Aquí puedes explorar y gestionar tus archivos almacenados.

¿Prefieres una terminal? Transloadit Storage es compatible con S3, y tu Auth Key y tu Auth Secret son sus credenciales. El slug de tu Workspace es el bucket:
set -a; . ./.env; set +a
export AWS_ACCESS_KEY_ID="$TRANSLOADIT_KEY" AWS_SECRET_ACCESS_KEY="$TRANSLOADIT_SECRET"
export AWS_DEFAULT_REGION=us-east-1
aws --endpoint-url "${TRANSLOADIT_STORAGE_S3_ENDPOINT:-https://api2.transloadit.com/storage}" \
s3 ls "s3://$TRANSLOADIT_WORKSPACE/uploads/"
# 2026-08-31 10:12:04 9309370 photo.jpg
Los siguientes ejemplos usan el listado de S3 y descargas con versiones. Comprueba qué operaciones y
permisos necesita tu cliente en lugar de dar por hecho que todas las funciones de AWS S3 están
disponibles. Después de ejecutar store.js dos veces, puedes listar ambas versiones mediante la
API de S3:
aws --endpoint-url "${TRANSLOADIT_STORAGE_S3_ENDPOINT:-https://api2.transloadit.com/storage}" \
s3api list-object-versions --bucket "$TRANSLOADIT_WORKSPACE" --prefix uploads/photo.jpg \
--query 'Versions[?Key==`uploads/photo.jpg`].[VersionId,IsLatest,LastModified]' --output text
# 9G2… True 2026-08-31T10:12:04+00:00
# 7Kq… False 2026-08-31T10:05:41+00:00
Después de subir dos veces a la misma ruta, descarga la versión anterior por su ID de versión. El
filtro de clave exacta evita seleccionar otro archivo cuyo nombre empiece por uploads/photo.jpg:
if PREVIOUS=$(aws --endpoint-url "${TRANSLOADIT_STORAGE_S3_ENDPOINT:-https://api2.transloadit.com/storage}" \
s3api list-object-versions --bucket "$TRANSLOADIT_WORKSPACE" --prefix uploads/photo.jpg \
--query 'Versions[?Key==`uploads/photo.jpg` && IsLatest==`false`] | [0].VersionId' --output text); then
if [ -n "$PREVIOUS" ] && [ "$PREVIOUS" != None ]; then
aws --endpoint-url "${TRANSLOADIT_STORAGE_S3_ENDPOINT:-https://api2.transloadit.com/storage}" \
s3api get-object --bucket "$TRANSLOADIT_WORKSPACE" --key uploads/photo.jpg \
--version-id "$PREVIOUS" photo-previous.jpg
else
printf '%s\n' 'No previous version exists. Upload the same path again first.'
fi
else
printf '%s\n' 'Could not list object versions; no download was attempted.' >&2
fi
Paso 3: sírvelo a través de Smart CDN
Mantén privado el directorio uploads/ del tutorial. Para entregar un archivo a un navegador, firma
una URL de Smart CDN para el Template integrado builtin/storage-serve@0.0.1, que lee el archivo de tu
almacenamiento y lo sirve. La firma incluye una caducidad que limita durante cuánto tiempo
Transloadit acepta esa firma. La caducidad no puede recuperar los bytes que un destinatario ya haya
descargado o almacenado en caché.
import { getSignedSmartCdnUrl } from '@transloadit/utils/node'
const url = getSignedSmartCdnUrl({
workspace: process.env.TRANSLOADIT_WORKSPACE,
template: 'builtin/storage-serve@0.0.1',
input: 'uploads/photo.jpg',
authKey: process.env.TRANSLOADIT_CDN_KEY,
authSecret: process.env.TRANSLOADIT_CDN_SECRET,
expiresAt: Date.now() + 60 * 60 * 1000, // valid for one hour
// Preview environments only; omit in production.
baseUrl: process.env.TRANSLOADIT_SMART_CDN_BASE_URL,
urlParams: Object.fromEntries(
new URLSearchParams(process.env.TRANSLOADIT_SMART_CDN_EXTRA_PARAMS ?? ''),
),
})
console.log(url)
curl --fail --silent --show-error --output photo-served.jpg "$(node --env-file=.env serve.js)"
La URL tiene este aspecto:
https://your-workspace-slug.tlcdn.com/builtin%2Fstorage-serve%400.0.1/uploads%2Fphoto.jpg?auth_key=…&exp=…&sig=sha256%3A….
Trátala como una credencial: cualquiera que la tenga puede usar su autorización, así que redirígela
a curl o entrégasela a un navegador en lugar de registrarla en los logs. La misma URL sin sus
parámetros auth_key, exp y sig se rechaza para este directorio privado,
independientemente de la configuración de Signature Authentication de tu Workspace. Storage también
admite prefijos publicados explícitamente y Templates integrados independientes para entrega
pública. Este tutorial no publica ningún prefijo; no publiques archivos privados solo para evitar
firmar URL.
Esto sirve el original (los 9,3 MB completos), también a un teléfono. El paso 4 muestra cómo servir en su lugar una versión redimensionada; en una página real, la usarías para cualquier cosa mayor que una miniatura.
Paso 4 (opcional): derivados al vuelo
builtin/storage-serve sirve el original. Para miniaturas, marcas de agua o conversiones de formato, creas
tu propio Template con /transloadit/import, un Robot de procesamiento y /file/serve.
Este usa /image/resize para redimensionar al ancho que se pasa en la URL:
import { Transloadit } from '@transloadit/node'
const client = new Transloadit({
authKey: process.env.TRANSLOADIT_KEY,
authSecret: process.env.TRANSLOADIT_SECRET,
endpoint: process.env.TRANSLOADIT_ENDPOINT,
})
const name = 'storage-thumb'
const template = {
steps: {
imported: { robot: '/transloadit/import', path: '${fields.input}' },
resized: { robot: '/image/resize', use: 'imported', width: '${fields.w}', imagemagick_stack: 'v3.0.0' },
served: { robot: '/file/serve', use: 'resized' },
},
}
// Search every page so rerunning the script also works in Workspaces with many Templates.
let existing
for await (const item of client.streamTemplates()) {
if (item.name === name) {
existing = item
break
}
}
if (existing) {
await client.editTemplate(existing.id, { name, template })
console.log(`Template ${name} updated`)
} else {
await client.createTemplate({ name, template })
console.log(`Template ${name} created`)
}
Firmar una URL para él es la misma llamada, con el nombre de tu propio Template y el ancho como parámetro de URL:
import { getSignedSmartCdnUrl } from '@transloadit/utils/node'
const url = getSignedSmartCdnUrl({
workspace: process.env.TRANSLOADIT_WORKSPACE,
template: 'storage-thumb',
input: 'uploads/photo.jpg',
authKey: process.env.TRANSLOADIT_CDN_KEY,
authSecret: process.env.TRANSLOADIT_CDN_SECRET,
expiresAt: Date.now() + 60 * 60 * 1000,
baseUrl: process.env.TRANSLOADIT_SMART_CDN_BASE_URL, // preview environments only
urlParams: {
w: 300,
...Object.fromEntries(new URLSearchParams(process.env.TRANSLOADIT_SMART_CDN_EXTRA_PARAMS ?? '')),
},
})
console.log(url)
node --env-file=.env create-template.js && \
curl --fail --silent --show-error --output photo-thumb.jpg "$(node --env-file=.env serve-thumb.js)"
# Template storage-thumb created
Smart CDN devuelve una versión de uploads/photo.jpg de 300 píxeles de ancho.

El Step /transloadit/import del Template personalizado también requiere acceso autenticado. Desactivar
Signature Authentication en el Workspace no hace pública esta importación privada. Para otros
Templates, consulta la documentación de autenticación antes de permitir el uso sin
firma.
Referencia: los dos Robots
/transloadit/storeacepta unpathopcional, cuyo valor predeterminado es${file.url_name}. Los destinos existentes fallan salvo que elijasoverwriteorename. Guarda los valores devueltosworkspace,asset_id,version_idy elpathfinal a partir del resultado del Step que produjo el archivo almacenado, no del resultado del Step de este Robot. Consulta la referencia del Robot de Storage para ver todas las opciones./transloadit/importacepta unpathde archivo o carpeta, o unasset_idcon unversion_idopcional para seleccionar los bytes conservados. Las importaciones de carpetas incluyen solo los elementos hijos directos, salvo que se establezcarecursive: true. Su salida es un archivo normal que otro Robot puede consumir conuse. Consulta la referencia del Robot de importación para conocer la autenticación y los selectores.
Qué acaba de pasar
- Un solo Robot,
/transloadit/store, guardó el archivo en el almacenamiento de tu Workspace. Sin bucket, sin IAM, sin credenciales en los Templates. - Una Biblioteca de archivos de la Console habilitada y las operaciones de S3 admitidas exponen los mismos archivos almacenados.
- Una URL firmada de Smart CDN sirve el original, y un pequeño Template propio sirve los derivados.
Siguientes pasos
- Para interfaces de subida en el navegador, explora Uppy. Mantén los Auth Secrets y los ejemplos de firma de este artículo en tu servidor, no en el código del navegador.
- Usa
/transloadit/importcon una ruta de carpeta yrecursive: truepara incluir subcarpetas al reprocesar una colección, por ejemplo, para crear nuevas miniaturas de toda una campaña.
