# Arquivos (GridFS) > files grava arquivos no MongoDB do App (bucket oon_files), isolados por tenant e compartilhados entre réplicas. O módulo `files` substitui a pasta local `uploads`, que é de cada pod: com várias réplicas, um arquivo gravado em uma delas não aparecia nas outras e se perdia no reinício. Agora os arquivos ficam em **GridFS** no banco do próprio App, no bucket `oon_files`, sempre com escopo de tenant. ## Uso em uma rota ```javascript title="backend/src/routes/anexos.js" const { defineRoutes, files, GenericError } = require("@oondemand/oon-core-back"); defineRoutes("/anexos", (router) => { router.private.post("/", { permission: "anexos.write" }, async (req, res) => { const { filename, contentType, base64 } = req.body ?? {}; if (!filename || !base64) throw new GenericError("Envie o arquivo.", { statusCode: 422, code: "ANEXO_INVALIDO" }); const saved = await files.forRequest(req).save({ data: Buffer.from(base64, "base64"), filename, contentType, metadata: { origem: "upload" }, }); res.status(201).json(saved); }); router.private.get("/:id", { permission: "anexos.read" }, async (req, res) => { await files.forRequest(req).send(res, req.params.id, { download: true }); }); router.private.get("/", { permission: "anexos.read" }, async (req, res) => { res.json(await files.forRequest(req).list({ limit: 50 })); }); }); ``` `files.forRequest(req)` usa o tenant de `req.accessContext`; sem tenant (Apps `none`), o escopo é global. ## API | Função | Descrição | |---|---| | `saveFile({ data, filename, contentType?, metadata?, maxBytes?, tenantId \| global })` | Grava `Buffer`, string ou `Readable`; devolve os metadados | | `getFileInfo(id, owner)` | Metadados no escopo | | `openFile(id, owner)` | `{ file, stream }` para leitura em stream | | `readFile(id, owner)` | `{ file, data: Buffer }` | | `listFiles(owner, { limit?, filename? })` | Lista do mais recente ao mais antigo (limite até 500) | | `deleteFile(id, owner)` | Remove; `{ deleted: true, id }` | | `sendFile(res, id, owner, { download? })` | Responde com `Content-Type`, `Content-Length`, `nosniff` e `Content-Disposition` | | `forRequest(req)` | Atalho com `save`, `info`, `open`, `read`, `list`, `remove`, `send` | Metadados retornados: ```json { "id": "…", "filename": "nota.pdf", "length": 48213, "contentType": "application/pdf", "tenantId": "t-1", "metadata": { "origem": "upload" }, "uploadDate": "…" } ``` ## Limites e erros | Código | Status | Causa | |---|---:|---| | `FILE_TENANT_REQUIRED` | 400 | Operação sem tenant e sem `global: true` | | `FILE_NOT_FOUND` | 404 | ID inexistente ou de outro tenant | | `FILE_TOO_LARGE` | 413 | Acima de `maxBytes` (padrão 25 MB) | | `FILE_NAME_INVALID` | 422 | Nome vazio, maior que 255 caracteres ou com `/`, `\` ou NUL | | `FILE_STORAGE_UNAVAILABLE` | 503 | Banco indisponível | > [!TIP] > Na exclusão de dados de uma licença encerrada, os arquivos e e-mails do tenant também são removidos pelo runtime. Fonte: https://sdk.oonapps.com/docs/backend/arquivos