Spaces:
Runtime error
Runtime error
Commit ·
e0039b5
1
Parent(s): 5bc6b5d
fix: normalize SFTP upload path relative to SFTP_ROOT
Browse files- sftp_store.py +22 -6
sftp_store.py
CHANGED
|
@@ -14,7 +14,7 @@ def sftp_test() -> str:
|
|
| 14 |
host = _env("SFTP_HOST")
|
| 15 |
port = int(_env("SFTP_PORT"))
|
| 16 |
user = _env("SFTP_USER")
|
| 17 |
-
pw
|
| 18 |
root = _env("SFTP_ROOT").rstrip("/") or "/"
|
| 19 |
|
| 20 |
transport = paramiko.Transport((host, port))
|
|
@@ -22,7 +22,6 @@ def sftp_test() -> str:
|
|
| 22 |
sftp = paramiko.SFTPClient.from_transport(transport)
|
| 23 |
|
| 24 |
try:
|
| 25 |
-
# verify root exists + list it
|
| 26 |
sftp.chdir(root)
|
| 27 |
sftp.listdir(".")
|
| 28 |
return "sftp ok"
|
|
@@ -34,10 +33,15 @@ def sftp_test() -> str:
|
|
| 34 |
|
| 35 |
|
| 36 |
def upload_bytes(remote_path: str, data: bytes) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
host = _env("SFTP_HOST")
|
| 38 |
port = int(_env("SFTP_PORT"))
|
| 39 |
user = _env("SFTP_USER")
|
| 40 |
-
pw
|
| 41 |
root = _env("SFTP_ROOT").rstrip("/") or "/"
|
| 42 |
|
| 43 |
transport = paramiko.Transport((host, port))
|
|
@@ -45,18 +49,30 @@ def upload_bytes(remote_path: str, data: bytes) -> None:
|
|
| 45 |
sftp = paramiko.SFTPClient.from_transport(transport)
|
| 46 |
|
| 47 |
try:
|
|
|
|
| 48 |
sftp.chdir(root)
|
| 49 |
-
|
| 50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
cur = "."
|
| 52 |
for part in parts:
|
|
|
|
|
|
|
| 53 |
cur = posixpath.join(cur, part)
|
| 54 |
try:
|
| 55 |
sftp.mkdir(cur)
|
| 56 |
except Exception:
|
| 57 |
pass
|
| 58 |
|
| 59 |
-
|
|
|
|
| 60 |
with sftp.open(full, "wb") as f:
|
| 61 |
f.write(data)
|
| 62 |
finally:
|
|
|
|
| 14 |
host = _env("SFTP_HOST")
|
| 15 |
port = int(_env("SFTP_PORT"))
|
| 16 |
user = _env("SFTP_USER")
|
| 17 |
+
pw = _env("SFTP_PASS")
|
| 18 |
root = _env("SFTP_ROOT").rstrip("/") or "/"
|
| 19 |
|
| 20 |
transport = paramiko.Transport((host, port))
|
|
|
|
| 22 |
sftp = paramiko.SFTPClient.from_transport(transport)
|
| 23 |
|
| 24 |
try:
|
|
|
|
| 25 |
sftp.chdir(root)
|
| 26 |
sftp.listdir(".")
|
| 27 |
return "sftp ok"
|
|
|
|
| 33 |
|
| 34 |
|
| 35 |
def upload_bytes(remote_path: str, data: bytes) -> None:
|
| 36 |
+
"""
|
| 37 |
+
Upload to SFTP_ROOT/<remote_path>.
|
| 38 |
+
remote_path should be RELATIVE (e.g. "pdfs/abc.pdf").
|
| 39 |
+
If someone passes "/inserio/pdfs/abc.pdf", we normalize it.
|
| 40 |
+
"""
|
| 41 |
host = _env("SFTP_HOST")
|
| 42 |
port = int(_env("SFTP_PORT"))
|
| 43 |
user = _env("SFTP_USER")
|
| 44 |
+
pw = _env("SFTP_PASS")
|
| 45 |
root = _env("SFTP_ROOT").rstrip("/") or "/"
|
| 46 |
|
| 47 |
transport = paramiko.Transport((host, port))
|
|
|
|
| 49 |
sftp = paramiko.SFTPClient.from_transport(transport)
|
| 50 |
|
| 51 |
try:
|
| 52 |
+
# go to the shared root first
|
| 53 |
sftp.chdir(root)
|
| 54 |
+
|
| 55 |
+
# normalize remote_path relative to root (avoid /inserio/inserio/... double prefix)
|
| 56 |
+
root_rel = root.strip("/")
|
| 57 |
+
rp = remote_path.lstrip("/")
|
| 58 |
+
if root_rel and rp.startswith(root_rel + "/"):
|
| 59 |
+
rp = rp[len(root_rel) + 1 :]
|
| 60 |
+
remote_path = rp
|
| 61 |
+
|
| 62 |
+
# ensure directories exist (relative to root)
|
| 63 |
+
parts = remote_path.split("/")[:-1]
|
| 64 |
cur = "."
|
| 65 |
for part in parts:
|
| 66 |
+
if not part:
|
| 67 |
+
continue
|
| 68 |
cur = posixpath.join(cur, part)
|
| 69 |
try:
|
| 70 |
sftp.mkdir(cur)
|
| 71 |
except Exception:
|
| 72 |
pass
|
| 73 |
|
| 74 |
+
# write file relative to root
|
| 75 |
+
full = posixpath.join(".", remote_path)
|
| 76 |
with sftp.open(full, "wb") as f:
|
| 77 |
f.write(data)
|
| 78 |
finally:
|