86 lines
2.7 KiB
Python
86 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
euni_seaweed.py — nahrávání/stahování souborů do SeaweedFS přes filer HTTP API.
|
|
|
|
Filer běží na Unraidu (default http://192.168.1.50:8888). Soubory se ukládají
|
|
podle cesty, která zrcadlí lokální strukturu: euni/<id>-<slug>/<typ>/<soubor>.
|
|
Filer metadata jdou do Mongo "seaweedfs" (na 192.168.1.76) — viz README v
|
|
U:\\PythonProject\\Janssen\\SeaweedFS\\.
|
|
|
|
Identifikátor pro vyžádání souboru = cesta (filer). Navíc se ukládají fid(y)
|
|
jednotlivých chunků (číslo souboru v SeaweedFS).
|
|
|
|
Přepsání endpointu: env EUNI_FILER.
|
|
"""
|
|
|
|
import os
|
|
from urllib.parse import quote
|
|
|
|
import requests
|
|
|
|
FILER = os.environ.get("EUNI_FILER", "http://192.168.1.50:8888")
|
|
PREFIX = "euni" # kořenová složka v SeaweedFS
|
|
|
|
|
|
def _url(remote_path):
|
|
return f"{FILER}/" + quote(remote_path.lstrip("/"), safe="/")
|
|
|
|
|
|
def entry_meta(remote_path, timeout=30):
|
|
"""Detailní metadata souboru (vč. chunků s fid), nebo None když neexistuje."""
|
|
try:
|
|
r = requests.get(_url(remote_path) + "?metadata=true", timeout=timeout)
|
|
if r.status_code == 200:
|
|
return r.json()
|
|
except requests.RequestException:
|
|
pass
|
|
return None
|
|
|
|
|
|
def exists(remote_path):
|
|
return entry_meta(remote_path) is not None
|
|
|
|
|
|
def upload(local_path, remote_path, timeout=900):
|
|
"""Nahraje soubor na filer. Vrátí dict: path, fids, size, md5."""
|
|
fname = os.path.basename(remote_path)
|
|
with open(local_path, "rb") as f:
|
|
r = requests.post(_url(remote_path), files={"file": (fname, f)},
|
|
timeout=timeout)
|
|
r.raise_for_status()
|
|
meta = entry_meta(remote_path) or {}
|
|
fids = [c.get("file_id") for c in (meta.get("chunks") or []) if c.get("file_id")]
|
|
return {
|
|
"path": remote_path,
|
|
"fids": fids,
|
|
"size": meta.get("FileSize"),
|
|
"md5": meta.get("Md5"),
|
|
}
|
|
|
|
|
|
def download(remote_path, local_path, timeout=900):
|
|
"""Stáhne soubor z fileru na lokální cestu. Vrátí velikost v bajtech."""
|
|
r = requests.get(_url(remote_path), stream=True, timeout=timeout)
|
|
r.raise_for_status()
|
|
os.makedirs(os.path.dirname(os.path.abspath(local_path)), exist_ok=True)
|
|
tmp = str(local_path) + ".part"
|
|
with open(tmp, "wb") as f:
|
|
for chunk in r.iter_content(chunk_size=65536):
|
|
if chunk:
|
|
f.write(chunk)
|
|
os.replace(tmp, local_path)
|
|
return os.path.getsize(local_path)
|
|
|
|
|
|
def ping():
|
|
try:
|
|
r = requests.get(f"{FILER}/?limit=1", headers={"Accept": "application/json"},
|
|
timeout=5)
|
|
return r.status_code == 200
|
|
except requests.RequestException:
|
|
return False
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("Filer:", FILER, "dostupný:" , ping())
|