# Upload de arquivos pela linha de comando O endpoint de upload já usado pelo gerenciador de arquivos também aceita clientes CLI: ```text POST /api/files/upload Authorization: Bearer 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: ```sh 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 Upload em uma linha, lendo o arquivo pelo `stdin`: ```sh cat arquivo.tar.gz | curl --fail-with-body --show-error --silent -X POST "https://notas.labexposed.com/api/files/upload" -H "Authorization: Bearer $NOTES_TOKEN" -F "file=@-;filename=arquivo.tar.gz" ``` `@-` diz ao `curl` para ler o conteúdo de `stdin`; `filename=...` define o nome armazenado pelo gerenciador. Defina `NOTES_TOKEN` com o token do servidor. O `curl -F` monta o multipart exigido pelo endpoint. Criando um alias no bash: ```sh # Função para upload rápido para o servidor de notas upload_nota() { local file="$1" if [ -z "$file" ] || [ ! -f "$file" ]; then echo "Erro: especifique um arquivo válido." >&2 return 1 fi local filename filename="$(basename "$file")" curl --fail-with-body --show-error --silent \ -X POST "https://notas.labexposed.com/api/files/upload" \ -H "Authorization: Bearer $NOTES_TOKEN" \ -F "file=@${file};filename=${filename}" } alias upnota='upload_nota' ``` Também é possível apontar o arquivo diretamente, sem pipe: ```sh 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: ```sh 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: ```sh 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: ```json { "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.