Files
notas-online/UPLOAD-CLI.md
T
lgcosta 61018a90b5
ci / check (push) Successful in 1m7s
feat(files): document CLI uploads
Document Bearer-authenticated multipart uploads with curl and Wget2. Return 413 for oversized multipart bodies and report attachment size limits accurately.
2026-11-06 08:35:19 -03:00

3.7 KiB

Upload de arquivos pela linha de comando

O endpoint de upload já usado pelo gerenciador de arquivos também aceita clientes CLI:

POST /api/files/upload
Authorization: Bearer <NOTES_TOKEN>
Content-Type: multipart/form-data

O campo multipart obrigatório é file. folder_id e note_id são opcionais. Sem eles, o arquivo fica na raiz e sem associação a nota. O nome enviado no multipart vira o nome do anexo; use nomes com letras/números, espaço, . , _ - ( ) # (até 200 caracteres).

Defina a URL pública da instância e o mesmo token configurado no servidor:

export NOTAS_URL='https://notas.exemplo.com'
export NOTES_TOKEN='seu-token'
FILE='./relatorio.pdf'

Não inclua /api em NOTAS_URL.

curl — caminho recomendado

O curl monta o multipart e envia o arquivo sem precisar construir o corpo à mão:

curl --fail-with-body --show-error --silent \
  -X POST "$NOTAS_URL/api/files/upload" \
  -H "Authorization: Bearer $NOTES_TOKEN" \
  -F "file=@$FILE"

Para colocar o arquivo em uma pasta e associá-lo a uma nota, envie também os IDs:

curl --fail-with-body --show-error --silent \
  -X POST "$NOTAS_URL/api/files/upload" \
  -H "Authorization: Bearer $NOTES_TOKEN" \
  -F "file=@$FILE" \
  -F "folder_id=$FOLDER_ID" \
  -F "note_id=$NOTE_ID"

folder_id e note_id precisam existir na instância. Obtenha os IDs existentes com GET /api/files/tree e GET /api/notes, autenticando com o mesmo Bearer token.

wget — GNU Wget2

O GNU Wget não possui equivalente a curl -F. Com Wget2, monte o multipart temporário e envie com --method=POST --body-file; --content-on-error preserva respostas JSON de erro. O exemplo também imprime o JSON de sucesso:

set -eu
boundary="----notas-upload-$(date +%s)-$$"
filename=${FILE##*/}
body=$(mktemp)
trap 'rm -f "$body"' EXIT HUP INT TERM

{
  if [ -n "${FOLDER_ID:-}" ]; then
    printf -- '--%s\r\nContent-Disposition: form-data; name="folder_id"\r\n\r\n%s\r\n' \
      "$boundary" "$FOLDER_ID"
  fi
  if [ -n "${NOTE_ID:-}" ]; then
    printf -- '--%s\r\nContent-Disposition: form-data; name="note_id"\r\n\r\n%s\r\n' \
      "$boundary" "$NOTE_ID"
  fi
  printf -- '--%s\r\n' "$boundary"
  printf 'Content-Disposition: form-data; name="file"; filename="%s"\r\n' "$filename"
  printf 'Content-Type: application/octet-stream\r\n\r\n'
  cat -- "$FILE"
  printf '\r\n--%s--\r\n' "$boundary"
} > "$body"

wget --quiet --content-on-error --method=POST \
  --header="Authorization: Bearer $NOTES_TOKEN" \
  --header="Content-Type: multipart/form-data; boundary=$boundary" \
  --body-file="$body" -O - "$NOTAS_URL/api/files/upload"

FOLDER_ID e NOTE_ID são opcionais. O exemplo requer GNU Wget2 (com --body-file, --method e --content-on-error); para GNU Wget 1.x, prefira o exemplo curl acima.

Resposta e erros

Sucesso retorna 201 Created e um JSON com o identificador, nome, tamanho, MIME, SHA-256 e URL do arquivo:

{
  "id": "a1b2c3d4e5f6",
  "name": "relatorio.pdf",
  "folder": "",
  "note": "",
  "size": 12345,
  "mime": "application/pdf",
  "sha256": "…",
  "created_at": "2026-11-06T12:00:00Z",
  "url": "/api/files/static/a1b2c3d4e5f6"
}
  • 401 — token ausente ou inválido; envie Authorization: Bearer $NOTES_TOKEN.
  • 400 — multipart inválido, campo file ausente, nome inválido, pasta/nota inexistente.
  • 413 — arquivo acima de 64 MiB, corpo multipart acima do limite ou quota total de anexos (2 GiB por instância) excedida.
  • 201 — upload concluído. Guarde id ou url para referenciar o anexo.

Uploads precisam passar por HTTPS em produção. Evite colocar o token literalmente no histórico do shell ou em scripts versionados; use variável de ambiente ou um gerenciador de segredos.