Armazene uploads e resultados sem configurar um bucket
Guardar arquivos processados muitas vezes significa configurar o armazenamento à parte: criar um bucket S3, escrever uma política de IAM e adicionar credenciais a um Template. É trabalho extra antes de chegar ao problema que você veio resolver.
O Transloadit Storage oferece uma alternativa para Workspaces admitidos. O Robot /transloadit/store
mantém os arquivos no armazenamento do seu Workspace, e uma URL assinada do Smart CDN entrega o
original ou um derivado gerado na hora. A Biblioteca de arquivos do Console e um endpoint compatível
com S3 oferecem formas de gerenciar esses arquivos quando a Biblioteca de arquivos está habilitada
para o seu Workspace.
O Transloadit Storage está em prévia privada. Se quiser testá-lo antes da disponibilidade geral, fale conosco sobre o acesso para o seu Workspace. Este tutorial também precisa de acesso à Biblioteca de arquivos, que nossa equipe habilita separadamente. Habilitar apenas o Storage não concede esse acesso.
Este tutorial leva um arquivo do seu disco para o Transloadit Storage e o traz de volta pelo Smart CDN em quatro passos curtos, com Node.js e o SDK oficial. Nenhum bucket é criado em momento algum.
O que você precisa
- Node.js 22 ou mais recente.
- Um Workspace admitido na prévia do Storage, com acesso à Biblioteca de arquivos habilitado.
- Duas Auth Keys criadas em Credenciais no Console: uma chave de API com
assemblies:write,dam:read,templates:readetemplates:writepara os exemplos abaixo, e uma chave separada de assinatura do Smart CDN. Para essa segunda chave, escolha Nova Auth Key e Entrega privada de imagens (assinatura do Smart CDN), que habilita o Smart CDN e seleciona apenassmart_cdn:sign. Fazer upload diretamente pelo S3 também exigedam:write. - A AWS CLI para os comandos S3 opcionais do passo 2.
- O slug do seu Workspace, ou seja, a parte depois de
/c/na URL do Console, por exemplomytransloadit-toystory-app.
Assemblies autorizadas por assemblies:write podem armazenar e importar arquivos por meio dos Robots
do Storage. Os escopos dam:read e dam:write controlam o acesso direto ao S3, não essas operações de
Assembly.
Habilitar o Smart CDN em uma chave não limita o que mais ela pode fazer; quem limita são as
permissões dela. Com apenas smart_cdn:sign, a chave não pode criar Assemblies avulsas nem gerenciar
o Storage. Mesmo assim, qualquer pessoa com o Auth Secret dela pode assinar URLs que executam
transformações na sua conta e entregam seus arquivos armazenados, então mantenha esse Auth Secret no
seu servidor como qualquer outro. Se ele vazar, exclua a chave e crie uma substituta.
Crie um projeto e um arquivo .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
O Node lê esse arquivo com --env-file, então não há dependência de dotenv. Para os comandos de shell
do passo 2, carregue-o com set -a; . ./.env; set +a e use esse mesmo terminal. Durante a prévia, você também pode
ter recebido de nós substituições de endpoints (TRANSLOADIT_ENDPOINT, TRANSLOADIT_STORAGE_S3_ENDPOINT,
TRANSLOADIT_SMART_CDN_BASE_URL, TRANSLOADIT_SMART_CDN_EXTRA_PARAMS); os scripts abaixo usam esses valores quando
presentes e, caso contrário, recorrem aos padrões de produção.
Coloque entre aspas os valores que contêm espaços ou caracteres de shell como & no
.env, para que o arquivo também possa ser carregado com segurança pelo comando de shell.
Passo 1: armazene um arquivo com /transloadit/store
/transloadit/store é um Robot de armazenamento como /s3/store, exceto que não precisa de credenciais
nem de bucket: ele grava no armazenamento do seu Workspace. path define onde o arquivo vai
parar; as pastas são criadas sob demanda, e ${file.name} é substituído para cada arquivo.
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…)
Essa é toda a parte de “configurar o armazenamento” deste tutorial. O arquivo agora fica em
uploads/photo.jpg dentro do seu Workspace. Se você armazenar no mesmo caminho de novo, recebe uma nova
versão (conflict_strategy: 'overwrite'). Você pode recuperar uma versão anterior enquanto ela estiver retida; o
versionamento não é uma promessa de retenção permanente nem substitui sua política de backup.
Passo 2: veja o arquivo no Console ou com as ferramentas S3 que você já tem
A Biblioteca de arquivos precisa ser habilitada para o seu Workspace pela nossa equipe. Depois disso, o proprietário, um administrador ou um membro comum do Workspace pode abri-la; um administrador de faturamento não pode. Habilitar apenas o Storage não libera a página nem o endpoint S3 dela.
Com o acesso habilitado, abra o Console, escolha seu Workspace e vá para Biblioteca de arquivos
(https://transloadit.com/c/<workspace-slug>/file-library/). A pasta uploads está lá, com
photo.jpg dentro. Aqui você pode navegar pelos seus arquivos armazenados e gerenciá-los.

Prefere o terminal? O Transloadit Storage é compatível com S3, e sua Auth Key e seu Auth Secret são as credenciais dele. O slug do seu Workspace é o 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
Os exemplos a seguir usam listagem S3 e downloads de versões específicas. Verifique as operações e
permissões de que seu cliente precisa em vez de presumir que todos os recursos do AWS S3 estão
disponíveis. Depois de executar store.js duas vezes, você pode listar as duas versões pela API 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
Depois de fazer upload para o mesmo caminho duas vezes, baixe a versão anterior pelo ID da versão. O
filtro de chave exata evita selecionar outro arquivo cujo nome comece com 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
Passo 3: entregue o arquivo pelo Smart CDN
Mantenha privado o diretório uploads/ do tutorial. Para entregar um arquivo a um navegador, assine uma
URL do Smart CDN para o Template integrado builtin/storage-serve@0.0.1, que lê o arquivo do seu armazenamento e o
entrega. A assinatura traz uma expiração que limita por quanto tempo a Transloadit aceita essa
assinatura. A expiração não consegue recuperar bytes que um destinatário já baixou ou armazenou em
cache.
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)"
A URL fica parecida com
https://your-workspace-slug.tlcdn.com/builtin%2Fstorage-serve%400.0.1/uploads%2Fphoto.jpg?auth_key=…&exp=…&sig=sha256%3A….
Trate-a como uma credencial: qualquer pessoa que a tenha pode usar a autorização dela, então passe-a
por pipe para curl ou entregue-a a um navegador em vez de registrá-la em log. A mesma URL sem os
parâmetros auth_key, exp e sig é recusada para este diretório privado, independentemente da
configuração de Signature Authentication do seu Workspace. O Storage também oferece suporte a
prefixos publicados explicitamente e a Templates integrados separados para entrega pública. Este
tutorial não publica nenhum prefixo; não publique arquivos privados só para evitar assinar URLs.
Isso entrega o original, com todos os seus 9,3 MB, inclusive para um celular. O passo 4 mostra como entregar uma versão redimensionada; em uma página real, você usaria isso para qualquer coisa maior que uma miniatura.
Passo 4 (opcional): derivados gerados na hora
builtin/storage-serve entrega o original. Para miniaturas, marcas-d’água ou conversões de formato, você cria seu
próprio Template com /transloadit/import, um Robot de processamento e /file/serve.
Este Template usa /image/resize para redimensionar para uma largura passada na 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`)
}
Assinar uma URL para ele é a mesma chamada, com o nome do seu próprio Template e a largura 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
O Smart CDN retorna uma versão de uploads/photo.jpg com 300 pixels de largura.

O Step /transloadit/import do Template personalizado também exige acesso autenticado. Desabilitar a
Signature Authentication do Workspace não torna pública esta importação privada. Para outros
Templates, consulte a documentação de autenticação antes de permitir uso sem assinatura.
Referência: os dois Robots
/transloadit/storeaceita umpathopcional, cujo padrão é${file.url_name}. Destinos existentes geram falha, a menos que você escolhaoverwriteourename. Salveworkspace,asset_id,version_ide opathfinal retornados no resultado do Step produtor. Consulte a referência do Robot do Storage para ver todas as opções./transloadit/importaceita umpathde arquivo ou pasta, ou umasset_idcom umversion_idopcional para selecionar bytes retidos. Importações de pasta incluem apenas os filhos diretos, a menos querecursive: trueesteja definido. A saída dele é um arquivo normal que outro Robot pode receber comuse. Consulte a referência do Robot de importação para ver autenticação e seletores.
O que aconteceu
- Um único Robot,
/transloadit/store, manteve o arquivo no armazenamento do seu Workspace. Sem bucket, sem IAM, sem credenciais em Templates. - Uma Biblioteca de arquivos do Console habilitada e as operações S3 suportadas expõem os mesmos arquivos armazenados.
- Uma URL assinada do Smart CDN entrega o original, e um pequeno Template seu entrega os derivados.
Próximos passos
- Para interfaces de upload no navegador, conheça o Uppy. Mantenha os Auth Secrets e os exemplos de assinatura deste artigo no seu servidor, não no código do navegador.
- Use
/transloadit/importcom um caminho de pasta erecursive: truepara incluir subpastas ao reprocessar uma coleção, por exemplo para gerar novas miniaturas para uma campanha inteira.
