Skip to content

Entrega de Imagens — Redimensionamento e Conversão

As rotas que servem binário de imagem aceitam parâmetros de entrega: a API converte e redimensiona na resposta, e o arquivo original permanece intacto no GridFS.

Rota Auth
GET /api/v1/archive-records/{file_id} Bearer (header ou ?token=)
GET /api/v1/archive-records-public/{token} Pública (token Fernet ou archive_token)
GET /api/v1/avatars/{file_id} Pública

Por que existe

Levantamento de 06/09/2026, sobre as 179 capas de vídeo em produção:

Métrica Valor
Peso total armazenado 224,2 MB
PNG (61 arquivos) 172,8 MB — 77% do peso
Página de 10 cards do painel ~12,5 MB
Mesmo acervo em WebP, sem reduzir um pixel 18,3 MB (−92%)

O gargalo não era resolução: era PNG grande. Com ?w=400 nos cards, a página de 10 capas cai para menos de 300 KB.

Parâmetros

Parâmetro Tipo Padrão Efeito
w int 16–4096 sem redimensionar Largura máxima em px; altura proporcional. Nunca amplia.
q int 1–100 82 Qualidade da compressão.
fmt webp | jpeg | original webp Formato de entrega. original desliga a transformação.

Fora de faixa → 422.

Compatibilidade

Sem nenhum dos três parâmetros, a resposta é exatamente a de hoje — os mesmos bytes, o mesmo Content-Type, sem headers novos. Consumidor existente não muda.

Qualquer formato de entrada (PNG, JPEG, WebP) sai como WebP. Arquivo que não é imagem conversível — PDF, GIF animado — é entregue no original, sem erro.

Exemplos

# card do painel: 400 px, WebP
GET /api/v1/archive-records/6a1f35646947bd2a32478341?w=400

# só converter, mantendo as dimensões
GET /api/v1/archive-records/6a1f35646947bd2a32478341?fmt=webp

# avatar em 96 px
GET /api/v1/avatars/507f1f77bcf86cd799439011?w=96

# escapar da transformação
GET /api/v1/archive-records/6a1f35646947bd2a32478341?fmt=original

Flutter:

Image.network('$baseUrl/api/v1/archive-records/$fileId?w=400');

Cache

Resposta transformada vem com ETag e Cache-Control: public, max-age=604800. Reenviar o ETag em If-None-Match devolve 304 sem corpo.

Do lado do servidor, cada derivada é gerada uma vez e guardada num bucket GridFS separado (img_cache), com expiração automática em 30 dias. O acervo original nunca é tocado.

Substituir um arquivo preserva o file_id

PUT /api/v1/upload-file/archive-records/{_id}/{file_id} grava o novo conteúdo sob o mesmo _id. Referências ao arquivo — thumbnail_horizontal de um vídeo, avatar_id de um usuário — continuam válidas, e as derivadas em cache do conteúdo antigo são descartadas.

Mudança de comportamento (06/09/2026)

Até então a rota criava um arquivo com id novo e trocava a referência no registro-pai; qualquer documento que apontasse para o id antigo passava a apontar para o vazio, sem erro. Quem reapontava referências manualmente após o PUT pode parar de fazê-lo.