Λήψη Αρχείων (/file)

4 λεπτά ανάγνωσης

Λήψη Αρχείων

Το endpoint /file σερβίρει δυαδικά αρχεία που παράγονται από μια συνάρτηση PostgreSQL — χωρίς base64 μέσα στο JSON-RPC. Ένα επιστρεφόμενο αρχείο αποστέλλεται ως έχει· πολλά αρχεία πακετάρονται σε αρχείο ZIP εν κινήσει.

POST /{prefix}/{database}/file

Η πιστοποίηση, η εναλλαγή ρόλου (SET LOCAL ROLE), το rate limiting και το όριο μεγέθους του request είναι ίδια με το /jsonrpc. Ο καλών χρειάζεται EXECUTE στη συνάρτηση.

Request

{
  "method": "api.export_documents",
  "params": { "count": 3 },
  "options": { "filename": "export.zip", "force_zip": false, "compression_level": 6 },
  "idempotencyKey": "optional"
}
ΠεδίοΠεριγραφή
methodΥποχρεωτικό. schema.function, καλείται ως fn(params::jsonb).
paramsΠερνά στη συνάρτηση ως jsonb (προεπιλογή {}).
options.filenameΌνομα του αρχείου/ZIP που λαμβάνεται. Προεπιλογή: το ίδιο το όνομα του αρχείου ή export-YYYYMMDD-HHMMSS.zip.
options.force_zipΕπιστρέφει πάντα ZIP, ακόμη και για ένα αρχείο.
options.compression_level0 = μόνο αποθήκευση, 1–9· προεπιλογή 6.

Συμβόλαιο βάσης δεδομένων

Η συνάρτηση δέχεται ένα όρισμα jsonb και επιστρέφει ένα σύνολο γραμμών. Τα path και content είναι υποχρεωτικά· τα mime_type και store_only είναι προαιρετικά.

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;
$$;
  • Το path πρέπει να είναι απλή σχετική διαδρομή, ασφαλής για εξαγωγή σε κάθε λειτουργικό σύστημα. Μια διαδρομή απορρίπτεται (το request αποτυγχάνει με 500 και το πρόβλημα καταγράφεται στο log) αν:
    • είναι κενή, μεγαλύτερη από 512 bytes, δεν είναι έγκυρο UTF-8 ή περιέχει χαρακτήρες ελέγχου·
    • είναι απόλυτη (/…, C:…) ή περιέχει backslash·
    • έχει κενό τμήμα ή τμήμα . ή ..·
    • έχει τμήμα που τελειώνει με τελεία ή κενό (τα Windows τα αφαιρούν, οπότε το ".. " θα γινόταν ..)·
    • περιέχει : (εναλλακτική ροή δεδομένων NTFS) ή οποιονδήποτε από τους χαρακτήρες < > " | ? *·
    • χρησιμοποιεί ως τμήμα δεσμευμένο όνομα συσκευής των Windows, με ή χωρίς επέκταση (CON, PRN, AUX, NUL, COM0–COM9, LPT0–LPT9)·
    • συγκρούεται με άλλη διαδρομή στην ίδια απάντηση: τα ονόματα συγκρίνονται χωρίς διάκριση πεζών-κεφαλαίων (τα a.txt και A.TXT συγκρούονται σε macOS/Windows) και ένα αρχείο δεν μπορεί να είναι ταυτόχρονα και φάκελος (a και a/b).
  • Το content με τιμή NULL σημαίνει κενό αρχείο.
  • Το mime_type χρησιμοποιείται μόνο αν είναι έγκυρος τύπος μέσου, αλλιώς προκύπτει από την επέκταση (εφεδρικά application/octet-stream).
  • Το store_only = true αποθηκεύει την εγγραφή ZIP χωρίς συμπίεση (απαιτείται π.χ. για το αρχείο mimetype του EPUB).

Απάντηση

Γραμμέςforce_zipΑποτέλεσμα
0οποιοδήποτε404 (σφάλμα JSON)· η συναλλαγή αναιρείται (rollback), άρα τίποτα από όσα έκανε η συνάρτηση δεν διατηρείται και το idempotencyKey δεν καταναλώνεται
1falseτο ίδιο το αρχείο, με τον τύπο μέσου του
1trueZIP με μία εγγραφή
≥ 2οποιοδήποτε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}}' -OJ

Το όνομα λήψης (options.filename ή το όνομα του ίδιου του αρχείου) καθαρίζεται (sanitised): οι διαχωριστές διαδρομής, τα εισαγωγικά και οι δεσμευμένοι χαρακτήρες γίνονται _, ενώ οι χαρακτήρες ελέγχου, παράκαμψης κατεύθυνσης κειμένου, μηδενικού πλάτους και διαχωρισμού γραμμής αφαιρούνται, ώστε ένα όνομα να μη μπορεί να μεταμφιεστεί σε αρχείο άλλου τύπου.

Τα σφάλματα επιστρέφονται πάντα ως JSON, ποτέ ως δυαδικά δεδομένα: 400 μη έγκυρο request, 401 μη πιστοποιημένος, 403 χωρίς δικαίωμα, 404 άγνωστη συνάρτηση ή καθόλου γραμμές, 413 η απάντηση υπερβαίνει το FILE_MAX_BYTES / FILE_MAX_ENTRIES, 500 η συνάρτηση απέτυχε ή επέστρεψε μη έγκυρη δομή.

Ασφαλές εκ κατασκευής

Η βάση δεδομένων ελέγχει μόνο ονόματα αρχείων, περιεχόμενα και τύπους μέσων — ποτέ τις κεφαλίδες HTTP. Οι απαντήσεις έχουν πάντα Content-Disposition: attachment μαζί με X-Content-Type-Options: nosniff, Content-Security-Policy: sandbox και Cache-Control: no-store, έτσι ώστε μια συνάρτηση που επιστρέφει text/html ή SVG να μην μπορεί να εκτελέσει script στο origin του API. Τα ονόματα αρχείων καθαρίζονται (sanitised). Ολόκληρο το αποτέλεσμα αποθηκεύεται προσωρινά στη μνήμη: το πραγματικό όριο ανά request είναι το FILE_MAX_BYTES συν η μεγαλύτερη μεμονωμένη γραμμή, επειδή ο driver της βάσης διαβάζει μια γραμμή ολόκληρη πριν ελεγχθεί το όριο — λάβετε υπόψη τον αριθμό των ταυτόχρονων λήψεων. Το ίδιο το ZIP αποστέλλεται σε ροή.

Ανακάλυψη

Μια συνάρτηση που επιστρέφει σύνολο γραμμών, δηλωμένη με RETURNS TABLE (…) ή παραμέτρους OUT που περιλαμβάνουν στήλες path και content, αναφέρεται από το capabilities με "kind": "file" και endpoint /file. Η προδιαγραφή OpenAPI τεκμηριώνει μια πραγματική λειτουργία POST /{prefix}/{database}/file (μόνο για ρόλους που μπορούν να εκτελέσουν συνάρτηση αρχείου)· οι συναρτήσεις αρχείων δεν εκτίθενται ως εργαλεία MCP.