From fb32e774fedb86374713a97f96c2b98549b4196b Mon Sep 17 00:00:00 2001 From: lshaw8317 Date: Sat, 1 Nov 2025 12:34:44 +0100 Subject: [PATCH 1/6] Adding download from url --- caterva2/api_utils.py | 8 ++++++-- caterva2/services/server.py | 17 ++++++++++++----- caterva2/tests/test_api.py | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/caterva2/api_utils.py b/caterva2/api_utils.py index d25a13b7..f7137b6f 100644 --- a/caterva2/api_utils.py +++ b/caterva2/api_utils.py @@ -157,8 +157,12 @@ def upload_file(localpath, remotepath, urlbase, auth_cookie=None): url = f"{urlbase}/api/upload/{remotepath}" headers = {"Cookie": auth_cookie} if auth_cookie else None - with open(localpath, "rb") as f: - response = client.post(url, files={"file": f}, headers=headers) + try: + with open(localpath, "rb") as f: + response = client.post(url, files={"file": f}, headers=headers) + response.raise_for_status() + except FileNotFoundError: # possibly a remote download url + response = client.post(url, files=localpath, headers=headers) response.raise_for_status() return pathlib.PurePosixPath(response.json()) diff --git a/caterva2/services/server.py b/caterva2/services/server.py index 7493554a..8e89a679 100644 --- a/caterva2/services/server.py +++ b/caterva2/services/server.py @@ -31,6 +31,7 @@ import dotenv import fastapi import furl +import httpx import markdown import nbconvert import nbformat @@ -956,7 +957,7 @@ def get_writable_path(path: pathlib.Path, user: db.User) -> pathlib.Path: @app.post("/api/upload/{path:path}") async def upload_file( path: pathlib.Path, - file: UploadFile, + file: UploadFile | str, user: db.User = Depends(current_active_user), ): """ @@ -966,8 +967,8 @@ async def upload_file( ---------- path : pathlib.Path The path to store the uploaded file. - file : UploadFile - The file to upload. + file : UploadFile | str + The file to upload (from local or remote source). Returns ------- @@ -983,10 +984,16 @@ async def upload_file( if abspath.is_dir(): abspath /= file.filename path /= file.filename - + print(abspath) # Check quota # TODO To be fair we should check quota later (after compression, zip unpacking etc.) - data = await file.read() + if isinstance(file, str): + async with httpx.AsyncClient(timeout=30.0) as client: + response = await client.get(url) + response.raise_for_status() + data = response.content + else: + data = await file.read() if abspath.suffix not in {".b2", ".b2frame", ".b2nd"}: schunk = blosc2.SChunk(data=data) newsize = schunk.nbytes diff --git a/caterva2/tests/test_api.py b/caterva2/tests/test_api.py index ea183fd8..174c9074 100644 --- a/caterva2/tests/test_api.py +++ b/caterva2/tests/test_api.py @@ -629,6 +629,38 @@ def test_upload(fnames, remove, root, examples_dir, tmp_path, auth_client): assert "Not Found" in str(e_info.value) +def test_upload_remote(examples_dir, tmp_path, auth_client): + if not auth_client: + pytest.skip("authentication support needed") + + root = "@public" + path, remotepath = ( + "https://github.com/ironArray/data-cat2-demo/blob/main/hdf5root-example.h5", + "myfile.h5", + ) + + remote_root = auth_client.get(root) + myroot = auth_client.get(TEST_CATERVA2_ROOT) + with contextlib.chdir(tmp_path): + # Now, upload the file to the remote root + remote_ds = remote_root.upload(path, remotepath) + # Check whether the file has been uploaded with the correct name + if remotepath: + if remotepath.endswith("/"): + assert remote_ds.name == remotepath + path.name + else: + assert remote_ds.name == remotepath + else: + assert remote_ds.name == str(path) + # Check removing the file + remote_removed = pathlib.Path(remote_ds.remove()) + assert remote_removed == remote_ds.path + # Check that the file has been removed + with pytest.raises(Exception) as e_info: + _ = remote_root[remote_removed] + assert "Not Found" in str(e_info.value) + + def test_upload_public_unauthorized(client, auth_client, examples_dir, tmp_path): if auth_client: pytest.skip("not authentication needed") From d3f8b5f6c29d03040f47051a6e5b5bbf777bc7a1 Mon Sep 17 00:00:00 2001 From: lshaw8317 Date: Mon, 3 Nov 2025 14:17:10 +0100 Subject: [PATCH 2/6] Working on this --- caterva2/api_utils.py | 18 ++++++--- caterva2/client.py | 50 ++++++++++++++++++++++++ caterva2/services/server.py | 77 +++++++++++++++++++++++++++++++++---- caterva2/tests/test_api.py | 12 +++--- 4 files changed, 138 insertions(+), 19 deletions(-) diff --git a/caterva2/api_utils.py b/caterva2/api_utils.py index f7137b6f..3e46eaf0 100644 --- a/caterva2/api_utils.py +++ b/caterva2/api_utils.py @@ -157,16 +157,22 @@ def upload_file(localpath, remotepath, urlbase, auth_cookie=None): url = f"{urlbase}/api/upload/{remotepath}" headers = {"Cookie": auth_cookie} if auth_cookie else None - try: - with open(localpath, "rb") as f: - response = client.post(url, files={"file": f}, headers=headers) - response.raise_for_status() - except FileNotFoundError: # possibly a remote download url - response = client.post(url, files=localpath, headers=headers) + with open(localpath, "rb") as f: + response = client.post(url, files={"file": f}, headers=headers) response.raise_for_status() return pathlib.PurePosixPath(response.json()) +def download_from_url(localpath, remotepath, urlbase, auth_cookie=None): + client = get_client() + url = f"{urlbase}/api/download_from_url/{remotepath}" + + headers = {"Cookie": auth_cookie} if auth_cookie else None + response = client.post(url, data={"url": localpath}, headers=headers) + response.raise_for_status() + return pathlib.PurePosixPath(response.json()) + + def unfold_file(remotepath, urlbase, auth_cookie=None): client = get_client() url = f"{urlbase}/api/unfold/{remotepath}" diff --git a/caterva2/client.py b/caterva2/client.py index 18739322..235ef4ac 100644 --- a/caterva2/client.py +++ b/caterva2/client.py @@ -239,6 +239,32 @@ def upload(self, localpath, remotepath=None): # Remove the first component of the upload path (the root name) and return a new File/Dataset return self[str(uploadpath.relative_to(self.name))] + def download_from_url(self, localpath, remotepath=None): + """ + Downloads a third party file via url to this root. + + Parameters + ---------- + localpath : str + Path of the file to upload. + remotepath : Path, optional + Remote path where the file will be uploaded. If not provided, the + file will be uploaded to the top level of this root. + + Returns + ------- + File + A instance of :class:`File` or :class:`Dataset`. + + """ + if remotepath is None: + remotepath = pathlib.PurePosixPath(self.name) / localpath + else: + remotepath = pathlib.PurePosixPath(self.name) / pathlib.PurePosixPath(remotepath) + uploadpath = self.client.download_from_url(localpath, remotepath) + # Remove the first component of the upload path (the root name) and return a new File/Dataset + return self[str(uploadpath.relative_to(self.name))] + class File: def __init__(self, root, path): @@ -1118,6 +1144,30 @@ def upload(self, localpath, dataset): auth_cookie=self.cookie, ) + def download_from_url(self, localpath, dataset): + """ + Downloads a remote dataset to a remote repository. + + Parameters + ---------- + localpath : Path + Url to the remote third party dataset. + dataset : Path + Remote path to upload the dataset to. + + Returns + ------- + Path + Path of the uploaded file on the server. + """ + urlbase, _ = _format_paths(self.urlbase) + return api_utils.download_from_url( + localpath, + dataset, + urlbase, + auth_cookie=self.cookie, + ) + def append(self, remotepath, data): """ Appends data to the remote location. diff --git a/caterva2/services/server.py b/caterva2/services/server.py index 8e89a679..fbfa1da5 100644 --- a/caterva2/services/server.py +++ b/caterva2/services/server.py @@ -984,16 +984,79 @@ async def upload_file( if abspath.is_dir(): abspath /= file.filename path /= file.filename - print(abspath) + # Check quota # TODO To be fair we should check quota later (after compression, zip unpacking etc.) - if isinstance(file, str): - async with httpx.AsyncClient(timeout=30.0) as client: - response = await client.get(url) - response.raise_for_status() - data = response.content + data = await file.read() + if abspath.suffix not in {".b2", ".b2frame", ".b2nd"}: + schunk = blosc2.SChunk(data=data) + newsize = schunk.nbytes else: - data = await file.read() + newsize = len(data) + + if settings.quota: + try: + oldsize = abspath.stat().st_size + except FileNotFoundError: + oldsize = 0 + + total_size = get_disk_usage() - oldsize + newsize + if total_size > settings.quota: + detail = "Upload failed because quota limit has been exceeded." + raise fastapi.HTTPException(detail=detail, status_code=400) + + # If regular file, compress it + abspath.parent.mkdir(exist_ok=True, parents=True) + if abspath.suffix not in {".b2", ".b2frame", ".b2nd", ".h5", ".hdf5"}: + data = schunk.to_cframe() + abspath = abspath.with_suffix(abspath.suffix + ".b2") + + # Write the file + with open(abspath, "wb") as f: + f.write(data) + + # Return the urlpath + return str(path) + + +@app.post("/api/download_from_url/{path:path}") +async def download_from_url( + path: pathlib.Path, + file_url: str, + user: db.User = Depends(current_active_user), +): + """ + Download a file from a url to a root. + + Parameters + ---------- + path : pathlib.Path + The path to store the uploaded file. + file : str + The file to upload (from remote source). + + Returns + ------- + str + The path of the uploaded file. + """ + if not user: + raise srv_utils.raise_unauthorized("Uploading requires authentication") + + # Get the absolute path for this user + abspath = get_writable_path(path, user) + # We may upload a new file, or replace an existing file + if abspath.is_dir(): + abspath /= file.filename + path /= file.filename + + # Check quota + # TODO To be fair we should check quota later (after compression, zip unpacking etc.) + async with httpx.AsyncClient(follow_redirects=True, timeout=None) as client: + response = await client.get(url) + response.raise_for_status() + data = response.content + if abspath.suffix not in {".b2", ".b2frame", ".b2nd"}: schunk = blosc2.SChunk(data=data) newsize = schunk.nbytes diff --git a/caterva2/tests/test_api.py b/caterva2/tests/test_api.py index 174c9074..0437e606 100644 --- a/caterva2/tests/test_api.py +++ b/caterva2/tests/test_api.py @@ -629,22 +629,22 @@ def test_upload(fnames, remove, root, examples_dir, tmp_path, auth_client): assert "Not Found" in str(e_info.value) -def test_upload_remote(examples_dir, tmp_path, auth_client): +def test_download_fromurl(examples_dir, tmp_path, auth_client): if not auth_client: pytest.skip("authentication support needed") root = "@public" path, remotepath = ( - "https://github.com/ironArray/data-cat2-demo/blob/main/hdf5root-example.h5", - "myfile.h5", + "https://github.com/ironArray/data-cat2-demo/blob/main/root-example/ds-1d.b2nd", + "myfile.b2nd", ) remote_root = auth_client.get(root) myroot = auth_client.get(TEST_CATERVA2_ROOT) with contextlib.chdir(tmp_path): - # Now, upload the file to the remote root - remote_ds = remote_root.upload(path, remotepath) - # Check whether the file has been uploaded with the correct name + # Now, download the file to the remote root + remote_ds = remote_root.download_from_url(path, remotepath) + # Check whether the file has been downloaded with the correct name if remotepath: if remotepath.endswith("/"): assert remote_ds.name == remotepath + path.name From e756b8da09b4c79dcbe96f2d7ada2d19fb77f2d5 Mon Sep 17 00:00:00 2001 From: lshaw8317 Date: Tue, 4 Nov 2025 14:18:53 +0100 Subject: [PATCH 3/6] Add test --- caterva2/api_utils.py | 2 +- caterva2/services/server.py | 10 +++++----- caterva2/tests/test_api.py | 2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/caterva2/api_utils.py b/caterva2/api_utils.py index 3e46eaf0..dfbf65b5 100644 --- a/caterva2/api_utils.py +++ b/caterva2/api_utils.py @@ -168,7 +168,7 @@ def download_from_url(localpath, remotepath, urlbase, auth_cookie=None): url = f"{urlbase}/api/download_from_url/{remotepath}" headers = {"Cookie": auth_cookie} if auth_cookie else None - response = client.post(url, data={"url": localpath}, headers=headers) + response = client.post(url, data={"file": localpath}, headers=headers) response.raise_for_status() return pathlib.PurePosixPath(response.json()) diff --git a/caterva2/services/server.py b/caterva2/services/server.py index fbfa1da5..37dae41b 100644 --- a/caterva2/services/server.py +++ b/caterva2/services/server.py @@ -957,7 +957,7 @@ def get_writable_path(path: pathlib.Path, user: db.User) -> pathlib.Path: @app.post("/api/upload/{path:path}") async def upload_file( path: pathlib.Path, - file: UploadFile | str, + file: UploadFile, user: db.User = Depends(current_active_user), ): """ @@ -967,8 +967,8 @@ async def upload_file( ---------- path : pathlib.Path The path to store the uploaded file. - file : UploadFile | str - The file to upload (from local or remote source). + file : UploadFile + The file to upload (from local source). Returns ------- @@ -1022,7 +1022,7 @@ async def upload_file( @app.post("/api/download_from_url/{path:path}") async def download_from_url( path: pathlib.Path, - file_url: str, + file: str = fastapi.Form(...), user: db.User = Depends(current_active_user), ): """ @@ -1053,7 +1053,7 @@ async def download_from_url( # Check quota # TODO To be fair we should check quota later (after compression, zip unpacking etc.) async with httpx.AsyncClient(follow_redirects=True, timeout=None) as client: - response = await client.get(url) + response = await client.get(file) response.raise_for_status() data = response.content diff --git a/caterva2/tests/test_api.py b/caterva2/tests/test_api.py index 0437e606..3116779e 100644 --- a/caterva2/tests/test_api.py +++ b/caterva2/tests/test_api.py @@ -641,6 +641,7 @@ def test_download_fromurl(examples_dir, tmp_path, auth_client): remote_root = auth_client.get(root) myroot = auth_client.get(TEST_CATERVA2_ROOT) + arr_ = myroot["ds-1d.b2nd"] with contextlib.chdir(tmp_path): # Now, download the file to the remote root remote_ds = remote_root.download_from_url(path, remotepath) @@ -652,6 +653,7 @@ def test_download_fromurl(examples_dir, tmp_path, auth_client): assert remote_ds.name == remotepath else: assert remote_ds.name == str(path) + np.testing.assert_array_equal(remote_ds[:], arr_[:]) # Check removing the file remote_removed = pathlib.Path(remote_ds.remove()) assert remote_removed == remote_ds.path From aa9bebaf9a18efbb37929383536b9e92ad7d226a Mon Sep 17 00:00:00 2001 From: Luke Shaw Date: Tue, 11 Nov 2025 07:47:13 +0100 Subject: [PATCH 4/6] Correct url in test --- caterva2/tests/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/caterva2/tests/test_api.py b/caterva2/tests/test_api.py index 3116779e..98e50bff 100644 --- a/caterva2/tests/test_api.py +++ b/caterva2/tests/test_api.py @@ -635,7 +635,7 @@ def test_download_fromurl(examples_dir, tmp_path, auth_client): root = "@public" path, remotepath = ( - "https://github.com/ironArray/data-cat2-demo/blob/main/root-example/ds-1d.b2nd", + "https://github.com/ironArray/data-cat2-demo/raw/refs/heads/main/root-example/ds-1d.b2nd", "myfile.b2nd", ) From 1fd89207d9de1045c47c62fc7d11283673da4801 Mon Sep 17 00:00:00 2001 From: lshaw8317 Date: Tue, 11 Nov 2025 12:45:21 +0100 Subject: [PATCH 5/6] Rename to load_from_url --- caterva2/api_utils.py | 4 ++-- caterva2/client.py | 20 ++++++++++---------- caterva2/services/server.py | 10 +++++----- caterva2/tests/test_api.py | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/caterva2/api_utils.py b/caterva2/api_utils.py index dfbf65b5..feaa0976 100644 --- a/caterva2/api_utils.py +++ b/caterva2/api_utils.py @@ -163,9 +163,9 @@ def upload_file(localpath, remotepath, urlbase, auth_cookie=None): return pathlib.PurePosixPath(response.json()) -def download_from_url(localpath, remotepath, urlbase, auth_cookie=None): +def load_from_url(localpath, remotepath, urlbase, auth_cookie=None): client = get_client() - url = f"{urlbase}/api/download_from_url/{remotepath}" + url = f"{urlbase}/api/load_from_url/{remotepath}" headers = {"Cookie": auth_cookie} if auth_cookie else None response = client.post(url, data={"file": localpath}, headers=headers) diff --git a/caterva2/client.py b/caterva2/client.py index 235ef4ac..cccc9e9a 100644 --- a/caterva2/client.py +++ b/caterva2/client.py @@ -239,17 +239,17 @@ def upload(self, localpath, remotepath=None): # Remove the first component of the upload path (the root name) and return a new File/Dataset return self[str(uploadpath.relative_to(self.name))] - def download_from_url(self, localpath, remotepath=None): + def load_from_url(self, localpath, remotepath=None): """ - Downloads a third party file via url to this root. + Loads a third party file via url to this root. Parameters ---------- localpath : str - Path of the file to upload. + Url path of the file to get. remotepath : Path, optional - Remote path where the file will be uploaded. If not provided, the - file will be uploaded to the top level of this root. + Remote path where the file will be placed. If not provided, the + file will be placed in the top level of this root. Returns ------- @@ -261,7 +261,7 @@ def download_from_url(self, localpath, remotepath=None): remotepath = pathlib.PurePosixPath(self.name) / localpath else: remotepath = pathlib.PurePosixPath(self.name) / pathlib.PurePosixPath(remotepath) - uploadpath = self.client.download_from_url(localpath, remotepath) + uploadpath = self.client.load_from_url(localpath, remotepath) # Remove the first component of the upload path (the root name) and return a new File/Dataset return self[str(uploadpath.relative_to(self.name))] @@ -1144,16 +1144,16 @@ def upload(self, localpath, dataset): auth_cookie=self.cookie, ) - def download_from_url(self, localpath, dataset): + def load_from_url(self, localpath, dataset): """ - Downloads a remote dataset to a remote repository. + Loads a remote dataset to a remote repository. Parameters ---------- localpath : Path Url to the remote third party dataset. dataset : Path - Remote path to upload the dataset to. + Remote path to place the dataset into. Returns ------- @@ -1161,7 +1161,7 @@ def download_from_url(self, localpath, dataset): Path of the uploaded file on the server. """ urlbase, _ = _format_paths(self.urlbase) - return api_utils.download_from_url( + return api_utils.load_from_url( localpath, dataset, urlbase, diff --git a/caterva2/services/server.py b/caterva2/services/server.py index 37dae41b..cc380f6b 100644 --- a/caterva2/services/server.py +++ b/caterva2/services/server.py @@ -1019,21 +1019,21 @@ async def upload_file( return str(path) -@app.post("/api/download_from_url/{path:path}") -async def download_from_url( +@app.post("/api/load_from_url/{path:path}") +async def load_from_url( path: pathlib.Path, file: str = fastapi.Form(...), user: db.User = Depends(current_active_user), ): """ - Download a file from a url to a root. + Load a file from a url to a root. Parameters ---------- path : pathlib.Path - The path to store the uploaded file. + The path to store the file. file : str - The file to upload (from remote source). + The url to get the file (from remote source). Returns ------- diff --git a/caterva2/tests/test_api.py b/caterva2/tests/test_api.py index 98e50bff..4e0146d4 100644 --- a/caterva2/tests/test_api.py +++ b/caterva2/tests/test_api.py @@ -629,7 +629,7 @@ def test_upload(fnames, remove, root, examples_dir, tmp_path, auth_client): assert "Not Found" in str(e_info.value) -def test_download_fromurl(examples_dir, tmp_path, auth_client): +def test_loadfromurl(examples_dir, tmp_path, auth_client): if not auth_client: pytest.skip("authentication support needed") @@ -644,7 +644,7 @@ def test_download_fromurl(examples_dir, tmp_path, auth_client): arr_ = myroot["ds-1d.b2nd"] with contextlib.chdir(tmp_path): # Now, download the file to the remote root - remote_ds = remote_root.download_from_url(path, remotepath) + remote_ds = remote_root.load_from_url(path, remotepath) # Check whether the file has been downloaded with the correct name if remotepath: if remotepath.endswith("/"): From 73f2c5dcff5a0b57957f201e73b0005743bad82f Mon Sep 17 00:00:00 2001 From: lshaw8317 Date: Fri, 14 Nov 2025 09:06:27 +0100 Subject: [PATCH 6/6] Renaming of argument --- caterva2/api_utils.py | 4 ++-- caterva2/client.py | 14 +++++++------- caterva2/services/server.py | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/caterva2/api_utils.py b/caterva2/api_utils.py index feaa0976..b049b0db 100644 --- a/caterva2/api_utils.py +++ b/caterva2/api_utils.py @@ -163,12 +163,12 @@ def upload_file(localpath, remotepath, urlbase, auth_cookie=None): return pathlib.PurePosixPath(response.json()) -def load_from_url(localpath, remotepath, urlbase, auth_cookie=None): +def load_from_url(path_to_url, remotepath, urlbase, auth_cookie=None): client = get_client() url = f"{urlbase}/api/load_from_url/{remotepath}" headers = {"Cookie": auth_cookie} if auth_cookie else None - response = client.post(url, data={"file": localpath}, headers=headers) + response = client.post(url, data={"remote_url": path_to_url}, headers=headers) response.raise_for_status() return pathlib.PurePosixPath(response.json()) diff --git a/caterva2/client.py b/caterva2/client.py index cccc9e9a..deefd08c 100644 --- a/caterva2/client.py +++ b/caterva2/client.py @@ -239,13 +239,13 @@ def upload(self, localpath, remotepath=None): # Remove the first component of the upload path (the root name) and return a new File/Dataset return self[str(uploadpath.relative_to(self.name))] - def load_from_url(self, localpath, remotepath=None): + def load_from_url(self, path_to_url, remotepath=None): """ Loads a third party file via url to this root. Parameters ---------- - localpath : str + path_to_url : str Url path of the file to get. remotepath : Path, optional Remote path where the file will be placed. If not provided, the @@ -258,10 +258,10 @@ def load_from_url(self, localpath, remotepath=None): """ if remotepath is None: - remotepath = pathlib.PurePosixPath(self.name) / localpath + remotepath = pathlib.PurePosixPath(self.name) / path_to_url else: remotepath = pathlib.PurePosixPath(self.name) / pathlib.PurePosixPath(remotepath) - uploadpath = self.client.load_from_url(localpath, remotepath) + uploadpath = self.client.load_from_url(path_to_url, remotepath) # Remove the first component of the upload path (the root name) and return a new File/Dataset return self[str(uploadpath.relative_to(self.name))] @@ -1144,13 +1144,13 @@ def upload(self, localpath, dataset): auth_cookie=self.cookie, ) - def load_from_url(self, localpath, dataset): + def load_from_url(self, path_to_url, dataset): """ Loads a remote dataset to a remote repository. Parameters ---------- - localpath : Path + path_to_url : Path Url to the remote third party dataset. dataset : Path Remote path to place the dataset into. @@ -1162,7 +1162,7 @@ def load_from_url(self, localpath, dataset): """ urlbase, _ = _format_paths(self.urlbase) return api_utils.load_from_url( - localpath, + path_to_url, dataset, urlbase, auth_cookie=self.cookie, diff --git a/caterva2/services/server.py b/caterva2/services/server.py index cc380f6b..126f4c3e 100644 --- a/caterva2/services/server.py +++ b/caterva2/services/server.py @@ -1022,7 +1022,7 @@ async def upload_file( @app.post("/api/load_from_url/{path:path}") async def load_from_url( path: pathlib.Path, - file: str = fastapi.Form(...), + remote_url: str = fastapi.Form(...), user: db.User = Depends(current_active_user), ): """ @@ -1032,8 +1032,8 @@ async def load_from_url( ---------- path : pathlib.Path The path to store the file. - file : str - The url to get the file (from remote source). + remote_url : str + The url from which to get the file (from remote source). Returns ------- @@ -1047,13 +1047,13 @@ async def load_from_url( abspath = get_writable_path(path, user) # We may upload a new file, or replace an existing file if abspath.is_dir(): - abspath /= file.filename - path /= file.filename + abspath /= remote_url.filename + path /= remote_url.filename # Check quota # TODO To be fair we should check quota later (after compression, zip unpacking etc.) async with httpx.AsyncClient(follow_redirects=True, timeout=None) as client: - response = await client.get(file) + response = await client.get(remote_url) response.raise_for_status() data = response.content