Skip to Content

Przechowywanie plików

Każdy backend danych aplikacji otrzymuje obok swoich tabel prywatny magazyn obiektów. Podczas gdy backend danych przechowuje wiersze szeregów czasowych, przechowywanie plików mieści wszystko, co nie mieści się w wierszu: klatki z kamery, raporty PDF, obrazy firmware, klipy audio, eksporty.

Oba mechanizmy zaprojektowano do wspólnego używania. Zapisanie pliku zwraca ci trwały adres URL, a zamierzony wzorzec to wpisanie tego adresu URL do kolumny tabeli za jednym zamachem — widget na panelu wyrenderuje wtedy obraz bez żadnej dodatkowej pracy:

info = await ironflock.files.put("part-1.jpg", jpeg_bytes, content_type="image/jpeg") await ironflock.publish_to_table("inspections", part_id="1", photo_url=info.url)

Pełne API klienta — odczyt, wyświetlanie listy, wykorzystanie, linki do udostępniania, duże obiekty, kody błędów — jest opisane w dokumentacji SDK. Ta strona omawia stronę platformy: jak magazyn jest deklarowany, zarządzany, udostępniany i obsługiwany.

Jak to działa

  1. Opcjonalnie zadeklaruj sekcję files: w .ironflock/data-template.yml.
  2. Gdy użytkownik zainstaluje twoją aplikację w projekcie, IronFlock tworzy dla niej prywatny obszar przechowywania — dokładnie tak, jak tworzy bazę danych projektu.
  3. Twój kod brzegowy zapisuje i odczytuje obiekty przez API files z SDK.
  4. Odinstalowanie aplikacji całkowicie usuwa jej magazyn: każdy obiekt i każde poświadczenie, tak samo jak usuwany jest schemat bazy danych.

Podobnie jak baza danych, magazyn jest per projekt. Ta sama aplikacja zainstalowana w dwóch projektach otrzymuje dwa całkowicie odrębne obszary przechowywania, a ty jako deweloper aplikacji nie masz dostępu do żadnego z nich — dane należą do użytkownika uruchamiającego twoją aplikację.

Zerowa konfiguracja jest poprawną konfiguracją: aplikacja bez sekcji files: i tak otrzymuje jedną przestrzeń nazw o nazwie default, więc files.put(...) działa od razu w każdej aplikacji.

Deklarowanie magazynu w szablonie danych

Sekcja files: znajduje się obok data: w data-template.yml:

files: description: Camera frames and generated inspection reports. # Budżet magazynu, jaki aplikacja SUGERUJE dla siebie, w bajtach (tutaj 5 GiB). # Użytkownik projektu może go nadpisać; egzekwowane jest jego ustawienie. quotaBytes: 5368709120 namespaces: - name: frames description: Raw camera frames, one JPEG per inspected part. contentTypes: ["image/jpeg"] maxObjectBytes: 20971520 retention: { deleteAfter: 30 days } - name: reports description: Generated PDF inspection reports. contentTypes: ["application/pdf"] private: true

Przestrzenie nazw

Przestrzeń nazw to prefiks klucza, z którym powiązane są zasady. Nie jest to osobny bucket magazynu — każda przestrzeń nazw aplikacji znajduje się w jej jednym obszarze przechowywania, a nazwa przestrzeni nazw staje się po prostu pierwszym segmentem ścieżki przechowywania każdego obiektu.

To rozróżnienie mówi ci, kiedy zadeklarować przestrzeń nazw:

  • Porządkujesz pliki? Używaj ścieżek kluczy — 2026/03/part-1.jpg — wewnątrz przestrzeni nazw default. Klucze w stylu folderów to normalny przypadek.
  • Inne reguły dla zbioru obiektów? Zadeklaruj przestrzeń nazw. Reguły to jedyne, co dodaje przestrzeń nazw.

Reguły, jakie może nieść przestrzeń nazw:

PoleZnaczenie
nameMałe litery, cyfry i myślniki, zaczynające się od litery. sys, system, ironflock oraz ironflock-* są zarezerwowane
descriptionWyświetlany użytkownikom i czytelny dla agentów AI
privateWyklucza przestrzeń nazw z dostępu między aplikacjami. Domyślnie false (udostępniona) — dokładnie tak jak tabele
contentTypesDozwolone typy MIME, dozwolone globy (image/*). Domyślnie: dowolne
maxObjectBytesNajwiększy pojedynczy obiekt, do 5 GiB. Domyślnie 100 MiB
retention.deleteAfterObiekty starsze niż podana wartość są automatycznie usuwane (30 days, 2 weeks, 1 year, …)

Budżet magazynu

quotaBytes deklaruje się raz dla całej aplikacji, a nie per przestrzeń nazw. Przestrzeń nazw to tylko prefiks klucza, więc budżet per prefiks nie miałby czego egzekwować — przydział dotyczy jednego obszaru przechowywania aplikacji, a sam magazyn obiektów egzekwuje go na każdej ścieżce zapisu, w tym przy bezpośrednich przesłaniach.

Istnieją dwie liczby, a różnica między nimi jest zamierzona:

  • Sugerowany przydział — to, o co prosi twój szablon. Stosowany przy pierwszej instalacji aplikacji.
  • Egzekwowany przydział — to, co ustawił użytkownik projektu. Gdy użytkownik zmieni budżet w ustawieniach przechowywania aplikacji, wygrywa jego wartość, a ponowne wdrożenie aplikacji jej nie resetuje.

Jeśli twój szablon nic nie mówi, obowiązuje wartość domyślna platformy (1 GiB dla backendów deweloperskich, 10 GiB dla produkcyjnych).

Retencja

Obiekty, które przekroczyły wiek deleteAfter swojej przestrzeni nazw, są usuwane automatycznie — plikowy odpowiednik tabelarycznej zasady dropAfter. Retencja działa wewnątrz magazynu obiektów tam, gdzie magazyn ją obsługuje, oraz jako codzienne zadanie platformy tam, gdzie jej nie obsługuje (urządzenia on-premises), więc zadeklarowana retencja zachowuje się wszędzie tak samo.

Trwałe adresy URL i panele

Każdy przechowywany obiekt ma stabilny adres URL w postaci https://files.ironflock.com/f/<backend>/<namespace>/<key>. Trzy właściwości sprawiają, że to właśnie jego warto wpisać do kolumny tabeli:

  • Nigdy nie wygasa. Adres URL jest czystym adresem; pozostaje ważny przez cały czas życia obiektu.
  • Nie jest linkiem publicznym. Każde żądanie przechodzi przez proxy uwierzytelniające, które sprawdza, czy żądający jest zalogowany i posiada dostęp READ do tego backendu danych — sprawdzane ponownie przy każdym pojedynczym żądaniu. Cofnięcie dostępu użytkownikowi natychmiast odbiera mu możliwość pobrania każdego pliku.
  • Renderuje się w <img>. Przeglądarka automatycznie wysyła swój plik cookie sesji, więc widget na panelu może użyć tego adresu URL w <img src>, <video src> lub w linku do pobrania, bez udziału JavaScript.

Aby przekazać plik komuś spoza projektu, share_url z SDK tworzy zamiast tego wygasający link na okaziciela — zobacz udostępnianie obiektów, aby dowiedzieć się, którego kiedy użyć.

Duże pliki

Transfery do 6 MiB przechodzą jako pojedyncze wywołanie przez system komunikatów. Wszystko większe jest przesyłane bezpośrednio między urządzeniem a magazynem obiektów przez HTTPS — SDK przełącza się automatycznie, strumieniuje z dysku i na dysk, a wielogigabajtowy plik nigdy nie musi mieścić się w pamięci. Górny limit pojedynczego przesłania to 5 GiB.

Ścieżka bezpośrednia wymaga, aby urządzenie miało dostęp do hosta magazynu obiektów (s3.ironflock.com), a nie tylko do routera komunikatów. Jeśli fabryczne proxy przepuszcza wyłącznie ruch do routera, duże transfery kończą się jawnym kodem PRESIGN_UNREACHABLE, a nie ogólnym błędem — a zegar urządzenia rozbieżny o więcej niż 15 minut kończy się kodem CLOCK_SKEW, który jest wezwaniem do sprawdzenia NTP, a nie poświadczeń.

Udostępnianie plików między aplikacjami

Dostęp do plików między aplikacjami korzysta z tej samej zgody co dostęp do tabel między aplikacjami. Jest jeden przełącznik: gdy użytkownik projektu przyzna aplikacji B dostęp do danych aplikacji A (zgoda data_access w ustawieniach aplikacji), to przyznanie obejmuje tabele A oraz nieprywatne przestrzenie nazw plików A. Cofnięcie go cofa oba.

To, co twoja aplikacja kontroluje jako dostawca, to flaga private per przestrzeń nazw:

  • private: false (wartość domyślna) — aplikacje posiadające przyznany dostęp do danych mogą ją odczytywać (nigdy do niej zapisywać).
  • private: true — przestrzeń nazw jest niewidoczna dla innych aplikacji, kropka, nawet przy przyznanym dostępie.

Odzwierciedla to dokładnie korzystanie z danych innych aplikacji: przestrzenie nazw i tabele mają tę samą wartość domyślną. Bez zgody użytkownika projektu nic nie jest udostępniane — private: jedynie zawęża to, co widzi już uprawniony czytelnik, i nie jest samą zgodą.

Widok użytkownika

Użytkownicy projektu widzą i zarządzają magazynem twojej aplikacji w dwóch miejscach:

  • Widok danych pokazuje wpis Pliki obok tabel i widoków każdej aplikacji — przeszukiwalną listę każdego przechowywanego obiektu wraz z rozmiarem, typem i datą modyfikacji oraz pobieraniem per plik.
  • Ustawienia przechowywania aplikacji pokazują wykorzystanie (bajty i liczbę obiektów), egzekwowany budżet obok sugestii twojej aplikacji, element sterujący do zmiany budżetu oraz akcję Usuń wszystkie pliki — plikowy bliźniak opróżnienia wszystkich tabel. Usunięcie potwierdza się, wpisując nazwę aplikacji, i nie można go cofnąć.
  • Asystent AI może wyświetlać, przeszukiwać i odczytywać te pliki w imieniu użytkownika. Obowiązuje ta sama kontrola DATABACKEND/READ, więc nigdy nie pokaże pliku, którego użytkownik nie mógłby otworzyć samodzielnie. Przeszukuje ścieżki plików, a nie ich zawartość, i odczytuje pliki tekstowe, obrazy oraz pliki PDF — archiwów i innych formatów binarnych odczytać nie potrafi.

Podobnie jak w przypadku tabel, są to dane użytkownika: może je przeglądać, ograniczać i usuwać bez twojego udziału.

Bezpośredni dostęp S3

Dla wszystkiego poza SDK — analityka z DuckDB, nocnej kopii zapasowej rclone, potoku BI — użytkownik projektu może wydać poświadczenia S3 tylko do odczytu per aplikacja z ustawień przechowywania aplikacji.

Każde poświadczenie jest ograniczone do obszaru przechowywania tej jednej aplikacji: poświadczenie wydane dla aplikacji A nie działa na pliki aplikacji B — strukturalnie, ponieważ zasady przechowywania B po prostu nigdy go nie wskazują. Projekt może posiadać kilka poświadczeń per aplikacja (jedno na konsumenta: zadanie CI, skrypt kopii zapasowej, laptop), a cofnięcie jednego pozostawia pozostałe działające. Na tym też polega rotacja: jeśli klucz wycieknie, wydaj drugie poświadczenie, przenieś na nie konsumenta, cofnij pierwsze — żaden inny konsument nie zostaje naruszony.

Sekret jest wyświetlany jednokrotnie, przy tworzeniu. Wydanie wymaga dostępu do odczytu backendu danych tej aplikacji — tego samego uprawnienia, które w ogóle pozwala odczytywać te pliki, więc poświadczenie nigdy nie poszerza niczyjego zasięgu.

# rclone rclone config create myapp s3 provider=Other \ endpoint=https://s3.ironflock.com \ access_key_id=ifs-key-3317-x7k2m secret_access_key=<shown once> rclone ls myapp:if-1042-3317
# DuckDB CREATE SECRET (TYPE S3, KEY_ID 'ifs-key-3317-x7k2m', SECRET '<shown once>', ENDPOINT 's3.ironflock.com'); SELECT * FROM read_parquet('s3://if-1042-3317/exports/*.parquet');

Ustawienia przechowywania pokazują punkt końcowy oraz dokładną nazwę bucketa, na który skierować klienta. Zwróć uwagę, że wylistowanie bucketów najwyższego poziomu (aws s3 ls bez argumentu) celowo nic nie zwraca — poświadczenie nie posiada żadnych bucketów; ma przyznany dostęp do jednego. Adresuj bucket bezpośrednio, jak powyżej.

Urządzenia on-premises

Przechowywanie plików działa identycznie na urządzeniu on-premises, z trzema różnicami wynikającymi z konstrukcji urządzenia:

  • Pliki są serwowane w tym samym origin pod własnym adresem urządzenia (/files/...) — bez dodatkowej nazwy DNS, bez dodatkowego certyfikatu, i działa to w instalacjach na zwykłym HTTP. Trwałe adresy URL oraz <img src> zachowują się dokładnie tak jak w chmurze.
  • Backend przechowywania urządzenia strumieniuje pobrania plików przez platformę, zamiast przekierowywać do osobnego hosta magazynu, więc usługa przechowywania nigdy nie jest wystawiana jako drugi origin.
  • Bezpośrednie poświadczenia S3 nie są dostępne na urządzeniach — wbudowany magazyn obiektów nie potrafi wyrazić przyznań dostępu per poświadczenie. Sekcja ta po prostu nie pojawia się tam w ustawieniach przechowywania. Wszystko pozostałe, w tym zachowanie dużych plików przez SDK oraz zadeklarowana retencja, działa tak samo.

Urządzenie odcięte od sieci (air-gapped) obsługuje cały ruch plików lokalnie: logo aplikacji, obrazy paneli oraz pobrania plików nie wymagają łączności z internetem.

Limity w skrócie

LimitWartośćSkąd pochodzi
Transfer inline (pojedyncze wywołanie)6 MiBZgłaszany w czasie działania; może zostać podniesiony po stronie serwera
Pojedynczy obiekt100 MiB domyślnie, 5 GiB maks.maxObjectBytes per przestrzeń nazw
Pojedyncze przesłanie5 GiBGórny limit pojedynczego PUT w magazynie obiektów; przesyłanie wieloczęściowe nie jest jeszcze dostępne
Budżet magazynudomyślnie 1 GiB dev / 10 GiB prodSugerowany przez szablon, decydowany przez użytkownika
Długość i znaki kluczaUTF-8, ścieżki rozdzielane /../, znaki sterujące oraz zarezerwowane prefiksy są odrzucane
Last updated on