Pobieranie plików (/file)
Pobieranie plików
Endpoint /file udostępnia pliki binarne generowane przez funkcję PostgreSQL — bez base64 wewnątrz JSON-RPC. Pojedynczy zwrócony plik jest wysyłany bez zmian; wiele plików jest pakowanych w locie do archiwum ZIP.
POST /{prefix}/{database}/fileUwierzytelnianie, przełączanie roli (SET LOCAL ROLE), rate limiting i limit rozmiaru żądania są identyczne jak w /jsonrpc. Wywołujący musi mieć EXECUTE na funkcji.
Żądanie
{
"method": "api.export_documents",
"params": { "count": 3 },
"options": { "filename": "export.zip", "force_zip": false, "compression_level": 6 },
"idempotencyKey": "optional"
}| Pole | Opis |
|---|---|
method | Wymagane. schema.function, wywoływana jako fn(params::jsonb). |
params | Przekazywane do funkcji jako jsonb (domyślnie {}). |
options.filename | Nazwa pobieranego pliku/ZIP-a. Domyślnie: nazwa samego pliku lub export-YYYYMMDD-HHMMSS.zip. |
options.force_zip | Zawsze zwraca ZIP, nawet dla pojedynczego pliku. |
options.compression_level | 0 = tylko przechowywanie, 1–9; domyślnie 6. |
Kontrakt z bazą danych
Funkcja przyjmuje jeden argument jsonb i zwraca zbiór wierszy. path i content są wymagane; mime_type i store_only są opcjonalne.
CREATE FUNCTION api.export_documents(params jsonb)
RETURNS TABLE (path text, content bytea, mime_type text, store_only boolean)
LANGUAGE sql AS $$
SELECT 'report.csv', convert_to('a,b' || E'\n' || '1,2', 'UTF8'), 'text/csv', false;
$$;pathmusi być zwykłą ścieżką względną, bezpieczną do rozpakowania w każdym systemie operacyjnym. Ścieżka jest odrzucana (żądanie kończy się błędem 500, a problem jest logowany), jeśli:- jest pusta, dłuższa niż 512 bajtów, nie jest poprawnym UTF-8 lub zawiera znaki sterujące;
- jest bezwzględna (
/…,C:…) lub zawiera odwrotny ukośnik; - ma pusty segment albo segment
.lub..; - ma segment kończący się kropką lub spacją (Windows je usuwa, więc
".. "stałoby się..); - zawiera
:(alternatywny strumień danych NTFS) lub którykolwiek ze znaków< > " | ? *; - używa zarezerwowanej nazwy urządzenia Windows jako segmentu, z rozszerzeniem lub bez (
CON,PRN,AUX,NUL,COM0–COM9,LPT0–LPT9); - koliduje z inną ścieżką w tej samej odpowiedzi: nazwy są porównywane bez rozróżniania wielkości liter (
a.txtiA.TXTkolidują w macOS/Windows), a plik nie może być jednocześnie katalogiem (aia/b).
contentrówneNULLoznacza pusty plik.mime_typejest używany tylko wtedy, gdy jest poprawnie sformułowanym typem mediów; w przeciwnym razie jest zgadywany na podstawie rozszerzenia (domyślnieapplication/octet-stream).store_only = truezapisuje wpis ZIP bez kompresji (potrzebne np. dla plikumimetypew EPUB).
Odpowiedź
| Wiersze | force_zip | Wynik |
|---|---|---|
| 0 | dowolnie | 404 (błąd JSON); transakcja jest wycofywana, więc nic, co zrobiła funkcja, nie zostaje zapisane, a idempotencyKey nie jest zużywany |
| 1 | false | sam plik, z jego typem mediów |
| 1 | true | ZIP z jednym wpisem |
| ≥ 2 | dowolnie | ZIP (application/zip) |
curl -X POST http://localhost:8080/db/my_database/file \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"method":"api.export_documents","params":{"count":3}}' -OJNazwa pobieranego pliku (options.filename lub nazwa samego pliku) jest sanityzowana: separatory ścieżek, cudzysłowy i znaki zarezerwowane zamieniane są na _, a znaki sterujące, nadpisujące kierunek tekstu, o zerowej szerokości i separatory wierszy są usuwane, więc nazwa nie może udawać pliku innego typu.
Błędy są zawsze w formacie JSON, nigdy binarne: 400 nieprawidłowe żądanie, 401 brak uwierzytelnienia, 403 brak uprawnień, 404 nieznana funkcja lub brak wierszy, 413 odpowiedź przekracza FILE_MAX_BYTES / FILE_MAX_ENTRIES, 500 funkcja zawiodła lub zwróciła nieprawidłową strukturę.
Bezpieczne z założenia
Baza danych kontroluje wyłącznie nazwy plików, zawartość i typy mediów — nigdy nagłówki HTTP. Odpowiedzi zawsze mają Content-Disposition: attachment wraz z X-Content-Type-Options: nosniff, Content-Security-Policy: sandbox i Cache-Control: no-store, więc funkcja zwracająca text/html lub SVG nie może uruchomić skryptu w origin API. Nazwy plików są sanityzowane. Cały wynik jest buforowany w pamięci: rzeczywista granica na żądanie to FILE_MAX_BYTES plus największy pojedynczy wiersz, ponieważ sterownik bazy danych czyta wiersz w całości, zanim limit może zostać sprawdzony — miej na uwadze liczbę równoczesnych pobrań. Sam ZIP jest przesyłany strumieniowo.
Wykrywanie
Funkcja zwracająca zbiór, zadeklarowana z RETURNS TABLE (…) lub parametrami OUT, które zawierają kolumny path i content, jest raportowana przez capabilities z "kind": "file" i endpointem /file. Specyfikacja OpenAPI dokumentuje prawdziwą operację POST /{prefix}/{database}/file (tylko dla ról, które mogą wykonać funkcję plikową); funkcje plikowe nie są udostępniane jako narzędzia MCP.