Archivos
Integración por directorio: el CMS lee archivos que el origen deposita en una carpeta (FILE_WATCH)
y graba archivos en una carpeta para quien solo consume archivos (FILE_WRITE). Es el camino para
balanza, cromatógrafo, espectrómetro, LIMS, SPC y sistemas legados que exportan CSV/TXT/XML.
Conexión
Registre el directorio en Conexiones Externas con el tipo Archivo:
| Campo | Rol |
|---|---|
| Directorio Base | Ruta tal como la ve el servidor del CMS — en contenedor, el punto de montaje del volumen |
| Validar escritura | La prueba de conexión y el Keep Alive también graban/borran un archivo temporal |
El CMS no habla SMB/NFS: un recurso compartido de red lo monta el sistema operativo (o el volumen
del contenedor) y de ahí en adelante es una ruta local. El docker-compose.yml monta una raíz
única en /data/arquivos (variable CMS_FILES_ROOT); cada conexión apunta a una subcarpeta de
ella, así que crear una integración nueva no exige tocar el compose.
Toda ruta configurada en la Recolección y en la Entrega es relativa al Directorio Base, y salir
de él con .. está bloqueado — incluso cuando el nombre del archivo viene de un {{alias}} del
payload.
Usted ve la ruta completa
Como usted escribe solo el trecho relativo, cada campo de carpeta o de archivo muestra justo debajo la ruta completa en el servidor, con el Directorio Base en gris y el trecho que usted controla destacado. Es el mismo patrón de la vista previa de URL de la Entrega HTTP.
El listado hace lo mismo con las tres rutas de una Recolección — carpeta monitoreada, carpeta de
procesados y carpeta de error. Las dos últimas son relativas al Directorio Base, y no a la carpeta
monitoreada: así las resuelve el servidor, y era justamente lo que nadie podía adivinar. En blanco,
valen processados y erro.
Si la Conexión de archivo de la Aplicación no tiene Directorio Base completado, la vista previa da lugar a un aviso — sin la raíz no hay ruta completa, y la lectura o grabación fallará en la primera ejecución.
Recolección — FILE_WATCH
El barrido corre cada Intervalo de Barrido, filtrando por Máscara (*.csv;*.txt, acepta *
y ?). Cada archivo elegible se convierte en uno o varios mensajes en la cola de la recolección.
| Campo | Para qué sirve |
|---|---|
| Estabilidad (ms) | El archivo solo se lee después de pasar ese tiempo sin cambiar de tamaño — evita leer algo aún en grabación |
| Tamaño Máximo (KB) | Por encima de eso el archivo va directo a la carpeta de error, con alerta de Error de Recolección |
| Modo de Emisión | Archivo entero (1 mensaje, contenido crudo) o Un mensaje por línea (con metadatos de origen) |
| Codificación | UTF-8, Latin-1, UTF-16 LE, ASCII o Binario (Base64) |
| Acción Tras la Lectura | Mover, Renombrar, Borrar o Ninguna |
En el modo un mensaje por línea el payload es siempre un envelope JSON:
{ "arquivo": "lote.csv", "caminho": "/data/arquivos/laboratorio/entrada/lote.csv", "linha": 42,
"conteudo": "A;B;C",
"modificadoEm": "2026-08-21T10:00:00.000Z", "recebidoEm": "2026-08-21T10:00:03.120Z" }En el modo archivo entero, el payload es el contenido crudo (XML/JSON llegan listos al Transformador), salvo que Incluir metadatos esté activado.
La acción Ninguna mantiene el control de lo ya leído solo en la memoria del CMS: reiniciar el servicio vuelve a recolectar todos los archivos aún presentes en la carpeta. Úsela solo en pruebas — en las demás acciones es el propio filesystem el que garantiza que nada se recolecta dos veces.
No hay parser de CSV/XML nativo: convierta con un Transformador, como en el resto del CMS.
Detectar a partir de un archivo
El botón Detectar a partir de un archivo lee una muestra de un archivo que ya está en la carpeta y completa encoding, modo de lectura, encabezado y máscara. Nada se altera en el archivo.
Es la misma detección que usa el catálogo de carpetas, y vale por el mismo motivo: encoding y delimitador son exactamente los campos que nadie acierta a la primera y que solo fallan con el primer archivo de verdad.
Concurrencia y fallas
Antes de leer, el archivo se renombra a <nombre>.cms-processando — un rename atómico que impide
que dos instancias del CMS apuntando a la misma carpeta recolecten el mismo archivo. Si la lectura o
la grabación del mensaje falla, el archivo va a la Carpeta de Error y dispara ERRO_COLETA. Un
directorio inaccesible marca la recolección como desconectada y dispara
CONEXAO_ARQUIVO_PERDIDA, sin detener las demás recolecciones.
Entrega — FILE_WRITE
La Ruta/Nombre del Archivo es el campo URI Post Message de la Definición, relativo al
Directorio Base y aceptando {{alias}} del payload — el mismo mecanismo del tópico MQTT:
saida/{{numeroOrdem}}.json| Campo | Rol |
|---|---|
| Modo de Escritura | Crear nuevo (falla si ya existe), Sobrescribir o Anexar |
| Crear directorio | Crea la carpeta de destino cuando todavía no existe |
| Escritura atómica | Graba en un .tmp y renombra al final, para que el consumidor nunca lea un archivo a medias |
Modelo de Contenido
Define qué va dentro del archivo. Vacío, graba el payload del mensaje como llegó. Completado,
graba ese texto con cada {{alias}} sustituido por el valor del payload — y aquí hay una sutileza que
vale conocer:
| Campo | Resuelve contra |
|---|---|
| Ruta/Nombre del Archivo | El payload original, antes del Transformador |
| Modelo de Contenido | El payload ya transformado, o sea, la salida del Transformador |
Use los filtros de escape siempre que el valor caiga dentro de una string: {{alias|json}},
{{alias|csv}}, {{alias|xml}}. Sin ellos, una comilla o un salto de línea en el dato rompe el
archivo generado — y el defecto solo aparece después, en el sistema legado que lo lea.
La opción Validar contenido generado (activada por defecto) verifica, antes de grabar, si el
resultado sigue siendo un documento válido del Content-Type de la Entrega (JSON o XML). Si no lo es,
la entrega falla con un error claro y entra en reintento, en vez de grabar un archivo corrupto en
silencio. El Content-Type text/plain no tiene qué validar.
En modo Anexar, termine el modelo con un salto de línea para que cada mensaje sea una línea del archivo.
El retorno grabado en payloadRetorno es {"caminho": "<ruta completa del archivo>", "bytes": N} —
JSON (y no texto puro) porque ese retorno puede reenviarse y ser leído por un Transformador como
{{caminho}}.