Skip to content

Commit 1deedb4

Browse files
[Fixes #13479] cannot upload geojson/3dtiles from zip file (#13480)
* [Fixes #13479] cannot upload geojson/3dtiles from zip file
1 parent 996e1a8 commit 1deedb4

File tree

10 files changed

+137
-91
lines changed

10 files changed

+137
-91
lines changed

geonode/upload/handlers/base.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ def get_task_list(cls, action) -> tuple:
7979
raise Exception("The requested action is not implemented yet")
8080
return cls.TASKS.get(action)
8181

82+
@property
83+
def have_table(self):
84+
return True
85+
8286
@property
8387
def default_geometry_column_name(self):
8488
return "geometry"
@@ -212,6 +216,12 @@ def pre_processing(self, files, execution_id, **kwargs):
212216
)
213217
# updating the execution id params
214218
orchestrator.update_execution_request_obj(_exec_obj, {"input_params": _data})
219+
# removing zip file
220+
if "zip_file" in files and os.path.exists(files["zip_file"]):
221+
os.remove(files["zip_file"])
222+
if "kmz_file" in files and os.path.exists(files["kmz_file"]):
223+
os.remove(files["kmz_file"])
224+
215225
return _data, execution_id
216226

217227
def fixup_name(self, name):

geonode/upload/handlers/common/remote.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ def has_serializer(data) -> bool:
6969
return RemoteResourceSerializer
7070
return False
7171

72+
@property
73+
def have_table(self):
74+
return False
75+
7276
@staticmethod
7377
def can_handle(_data) -> bool:
7478
"""

geonode/upload/handlers/common/vector.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ class BaseVectorFileHandler(BaseHandler):
101101
ira.UPSERT.value: ("start_import", "geonode.upload.upsert_data", "geonode.upload.refresh_geonode_resource"),
102102
}
103103

104+
@property
105+
def have_table(self):
106+
return True
107+
104108
@property
105109
def default_geometry_column_name(self):
106110
return "geometry"
@@ -179,6 +183,7 @@ def extract_params_from_data(_data, action=None):
179183
"resource_pk": _data.pop("resource_pk", None),
180184
"store_spatial_file": _data.pop("store_spatial_files", "True"),
181185
"action": _data.pop("action", "upload"),
186+
"upsert_key": _data.pop("upsert_key", None),
182187
}, _data
183188

184189
@staticmethod
@@ -687,7 +692,7 @@ def create_geonode_resource(
687692
saved_dataset.refresh_from_db()
688693

689694
# if dynamic model is enabled, we can save up with is the primary key of the table
690-
if settings.IMPORTER_ENABLE_DYN_MODELS:
695+
if settings.IMPORTER_ENABLE_DYN_MODELS and self.have_table:
691696
from django.db import connections
692697

693698
column = None
@@ -1182,7 +1187,7 @@ def _process_feature(
11821187

11831188
def extract_upsert_key(self, exec_obj, dynamic_model_instance):
11841189
# first we check if the upsert key is passed by the call
1185-
key = exec_obj.input_params.get("upsert_key")
1190+
key = exec_obj.input_params.get("upsert_key", "ogc_fid")
11861191
if not key:
11871192
# if the upsert key is not passed, we use the primary key as upsert key
11881193
# the primary key is defined in the Fields of the dynamic model

geonode/upload/handlers/geojson/handler.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import json
2020
import logging
2121
import os
22+
import zipfile
2223
from geonode.upload.utils import UploadLimitValidator
2324
from geonode.upload.handlers.common.vector import BaseVectorFileHandler
2425
from osgeo import ogr
@@ -74,6 +75,11 @@ def can_handle(_data) -> bool:
7475
if isinstance(base, str):
7576
with open(base, "r") as f:
7677
_file = json.loads(f.read())
78+
elif "zip_file" in _data:
79+
# if we have a zipfile we need to read the file content before proceed
80+
with zipfile.ZipFile(_data["zip_file"], "r") as z:
81+
with z.open(_file.name) as inner_file:
82+
_file = json.loads(inner_file.read().decode("utf-8"))
7783
else:
7884
_file = json.loads(base.read())
7985

geonode/upload/handlers/remote/tiles3d.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ def can_handle(_data) -> bool:
5353
return True
5454
return False
5555

56+
@property
57+
def have_table(self):
58+
return False
59+
5660
@staticmethod
5761
def is_valid_url(url, **kwargs):
5862
BaseRemoteResourceHandler.is_valid_url(url)

geonode/upload/handlers/tiles3d/handler.py

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import os
2222
from pathlib import Path
2323
import math
24+
import zipfile
25+
from geonode.assets.models import LocalAsset
2426
from geonode.layers.models import Dataset
2527
from geonode.resource.enumerator import ExecutionRequestAction as exa
2628
from geonode.upload.utils import UploadLimitValidator
@@ -84,7 +86,7 @@ def can_handle(_data) -> bool:
8486
if not base:
8587
return False
8688
ext = base.split(".")[-1] if isinstance(base, str) else base.name.split(".")[-1]
87-
if ext in ["json"] and Tiles3DFileHandler.is_3dtiles_json(base):
89+
if ext in ["json"] and Tiles3DFileHandler.is_3dtiles_json(base, **_data):
8890
return True
8991
except Exception:
9092
return False
@@ -123,9 +125,15 @@ def is_valid(files, user, **kwargs):
123125
return True
124126

125127
@staticmethod
126-
def is_3dtiles_json(_file):
127-
with open(_file, "r") as _readed_file:
128-
_file = json.loads(_readed_file.read())
128+
def is_3dtiles_json(_file, **kwargs):
129+
if "zip_file" in kwargs:
130+
# if we have a zipfile we need to read the file content before proceed
131+
with zipfile.ZipFile(kwargs["zip_file"], "r") as z:
132+
with z.open(_file.name) as inner_file:
133+
_file = json.loads(inner_file.read().decode("utf-8"))
134+
else:
135+
with open(_file, "r") as _readed_file:
136+
_file = json.loads(_readed_file.read())
129137
# required key described in the specification of 3dtiles
130138
# https://docs.ogc.org/cs/22-025r4/22-025r4.html#toc92
131139
is_valid = all(key in _file.keys() for key in ("asset", "geometricError", "root"))
@@ -225,25 +233,28 @@ def create_geonode_resource(
225233
asset=None,
226234
):
227235
# we want just the tileset.json as location of the asset
228-
asset.location = [path for path in asset.location if path.endswith(".json")]
229-
asset.save()
236+
# asset.location = [path for path in asset.location if path.endswith(".json")]
237+
# asset.save()
238+
exec_obj = orchestrator.get_execution_object(execution_id)
230239

231240
resource = super().create_geonode_resource(layer_name, alternate, execution_id, ResourceBase, asset)
241+
asset = self.create_asset_and_link(resource, files=exec_obj.input_params["files"], action=exec_obj.action)
232242

233-
# fixing-up bbox for the 3dtile object
234-
js_file = None
235-
with open(asset.location[0]) as _file:
236-
js_file = json.loads(_file.read())
243+
if isinstance(asset, LocalAsset):
244+
# fixing-up bbox for the 3dtile object
245+
js_file = None
246+
with open(asset.location[0]) as _file:
247+
js_file = json.loads(_file.read())
237248

238-
if not js_file:
239-
return resource
249+
if not js_file:
250+
return resource
240251

241-
if self._has_region(js_file):
242-
resource = self.set_bbox_from_region(js_file, resource=resource)
243-
elif self._has_sphere(js_file):
244-
resource = self.set_bbox_from_boundingVolume_sphere(js_file, resource=resource)
245-
else:
246-
resource = self.set_bbox_from_boundingVolume(js_file, resource=resource)
252+
if self._has_region(js_file):
253+
resource = self.set_bbox_from_region(js_file, resource=resource)
254+
elif self._has_sphere(js_file):
255+
resource = self.set_bbox_from_boundingVolume_sphere(js_file, resource=resource)
256+
else:
257+
resource = self.set_bbox_from_boundingVolume(js_file, resource=resource)
247258

248259
return resource
249260

geonode/upload/handlers/tiles3d/tests.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,6 @@ def test_set_bbox_from_bounding_volume_wit_transform(self):
301301
self.assertEqual(resource.bbox_y0, 40.03610390613993)
302302
self.assertEqual(resource.bbox_y1, 40.04895731654794)
303303

304-
os.remove("/tmp/tileset.json")
305-
306304
def test_set_bbox_from_bounding_volume_without_transform(self):
307305
# https://github.com/geosolutions-it/MapStore2/blob/master/web/client/api/__tests__/ThreeDTiles-test.js#L147-L180
308306
tilesetjson_file = {
@@ -347,8 +345,6 @@ def test_set_bbox_from_bounding_volume_without_transform(self):
347345
self.assertEqual(resource.bbox_y0, 86.81078622278615)
348346
self.assertEqual(resource.bbox_y1, 86.81124587650872)
349347

350-
os.remove("/tmp/tileset.json")
351-
352348
def test_set_bbox_from_bounding_volume_sphere_with_transform(self):
353349
# https://github.com/geosolutions-it/MapStore2/blob/master/web/client/api/__tests__/ThreeDTiles-test.js#L102-L146
354350
tilesetjson_file = {
@@ -396,8 +392,6 @@ def test_set_bbox_from_bounding_volume_sphere_with_transform(self):
396392
self.assertAlmostEqual(resource.bbox_y0, 40.042485645323616)
397393
self.assertAlmostEqual(resource.bbox_y1, 40.042575577526556)
398394

399-
os.remove("/tmp/tileset.json")
400-
401395
def test_set_bbox_from_bounding_volume_sphere_without_transform(self):
402396
# https://github.com/geosolutions-it/MapStore2/blob/master/web/client/api/__tests__/ThreeDTiles-test.js#L53C4-L79C8
403397
tilesetjson_file = {
@@ -425,8 +419,6 @@ def test_set_bbox_from_bounding_volume_sphere_without_transform(self):
425419
self.assertEqual(resource.bbox_y0, 86.81097108354597)
426420
self.assertEqual(resource.bbox_y1, 86.8110610157489)
427421

428-
os.remove("/tmp/tileset.json")
429-
430422
def test_set_bbox_from_bounding_volume_sphere_with_center_zero_without_transform(self):
431423
# https://github.com/geosolutions-it/MapStore2/blob/master/web/client/api/__tests__/ThreeDTiles-test.js#L53C4-L79C8
432424
# This test should not extract bbox from boundingVolume sphere with center 0, 0, 0
@@ -450,8 +442,6 @@ def test_set_bbox_from_bounding_volume_sphere_with_center_zero_without_transform
450442
)
451443
self.assertTrue(resource.bbox == self.default_bbox)
452444

453-
os.remove("/tmp/tileset.json")
454-
455445
def _generate_execid_asset(self):
456446
exec_id = orchestrator.create_execution_request(
457447
user=self.owner,

geonode/upload/tests/end2end/test_env2end_upsert.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ def setUp(self) -> None:
8080
self.admin.is_staff = True
8181
self.admin.save()
8282
for el in Dataset.objects.all():
83-
el.delete()
83+
try:
84+
el.delete()
85+
except: # noqa
86+
continue
8487

8588
def tearDown(self) -> None:
8689
super().tearDown()
@@ -193,7 +196,7 @@ def test_import_shapefile_upsert(self):
193196
payload = {_filename: open(_file, "rb") for _filename, _file in self.upsert_geojson.items()}
194197
payload["resource_pk"] = prev_dataset.pk
195198
payload["action"] = "upsert"
196-
payload["upsert_key"] = "ogc_fid"
199+
payload["upsert_key"] = "id"
197200

198201
# time to upsert the data
199202
self.client.force_login(self.admin)

geonode/upload/tests/fixture/upsert/original.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
},
1313
"properties": {
1414
"ogc_fid": 999,
15+
"id": 999,
1516
"st_area_shape": 192656942.39615256,
1617
"st_length_shape": 117499.50756699985,
1718
"ra_cira": 9,
Lines changed: 71 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,78 @@
11
{
2-
"type": "FeatureCollection",
3-
"features": [
2+
"type": "FeatureCollection",
3+
"features":
4+
[
45
{
5-
"type": "Feature",
6-
"geometry": {
7-
"type": "Point",
8-
"coordinates": [
9-
-47.20138110814478,
10-
-13.8281037379215
11-
]
12-
},
13-
"properties": {
14-
"ogc_fid": 999,
15-
"st_area_shape": 192656942.39615256,
16-
"st_length_shape": 117499.50756699985,
17-
"ra_cira": 9,
18-
"ra_nome": "THIS IS A CREATE",
19-
"ra_codigo": "THIS IS A CREATE",
20-
"ra_path": "http://localhost:8080",
21-
"ra_areakm2": 192.65694240000002
22-
}
6+
"type": "Feature",
7+
"geometry":
8+
{
9+
"type": "Point",
10+
"coordinates":
11+
[
12+
-47.20138110814478,
13+
-13.8281037379215
14+
]
15+
},
16+
"properties":
17+
{
18+
"ogc_fid": 999,
19+
"id": 999,
20+
"st_area_shape": 192656942.39615256,
21+
"st_length_shape": 117499.50756699985,
22+
"ra_cira": 9,
23+
"ra_nome": "THIS IS A CREATE",
24+
"ra_codigo": "THIS IS A CREATE",
25+
"ra_path": "http://localhost:8080",
26+
"ra_areakm2": 192.65694240000002
27+
}
2328
},
2429
{
25-
"type": "Feature",
26-
"geometry": {
27-
"type": "Point",
28-
"coordinates": [
29-
-47.20138110814478,
30-
-13.8281037379215
31-
]
32-
},
33-
"properties": {
34-
"ogc_fid": 123,
35-
"st_area_shape": 192656942.39615256,
36-
"st_length_shape": 117499.50756699985,
37-
"ra_cira": 9,
38-
"ra_nome": "THIS IS A CREATE",
39-
"ra_codigo": "THIS IS A CREATE",
40-
"ra_path": "http://localhost:8080",
41-
"ra_areakm2": 192.65694240000002
42-
}
30+
"type": "Feature",
31+
"geometry":
32+
{
33+
"type": "Point",
34+
"coordinates":
35+
[
36+
-47.20138110814478,
37+
-13.8281037379215
38+
]
39+
},
40+
"properties":
41+
{
42+
"ogc_fid": 123,
43+
"id": 123,
44+
"st_area_shape": 192656942.39615256,
45+
"st_length_shape": 117499.50756699985,
46+
"ra_cira": 9,
47+
"ra_nome": "THIS IS A CREATE",
48+
"ra_codigo": "THIS IS A CREATE",
49+
"ra_path": "http://localhost:8080",
50+
"ra_areakm2": 192.65694240000002
51+
}
4352
},
4453
{
45-
"type": "Feature",
46-
"geometry": {
47-
"type": "Point",
48-
"coordinates": [
49-
-47.20138110814478,
50-
-13.8281037379215
51-
]
52-
},
53-
"properties": {
54-
"ogc_fid": 1,
55-
"st_area_shape": 192656942.39615256,
56-
"st_length_shape": 117499.50756699985,
57-
"ra_cira": 9,
58-
"ra_nome": "THIS IS A CREATE",
59-
"ra_codigo": "THIS IS A CREATE",
60-
"ra_path": "http://localhost:8080",
61-
"ra_areakm2": 192.65694240000002
62-
}
54+
"type": "Feature",
55+
"geometry":
56+
{
57+
"type": "Point",
58+
"coordinates":
59+
[
60+
-47.20138110814478,
61+
-13.8281037379215
62+
]
63+
},
64+
"properties":
65+
{
66+
"ogc_fid": 1,
67+
"id": 1,
68+
"st_area_shape": 192656942.39615256,
69+
"st_length_shape": 117499.50756699985,
70+
"ra_cira": 9,
71+
"ra_nome": "THIS IS A CREATE",
72+
"ra_codigo": "THIS IS A CREATE",
73+
"ra_path": "http://localhost:8080",
74+
"ra_areakm2": 192.65694240000002
75+
}
6376
}
64-
]
65-
}
66-
77+
]
78+
}

0 commit comments

Comments
 (0)