提交 7df189622f3c5e2acb057ca35b26cd99cc408070

作者 nheweijun
1 个父辈 f1f7116b

从3.0整合新功能

@@ -8,15 +8,17 @@ from app.models import Database,db,DES,Table,Columns,TableVacuate @@ -8,15 +8,17 @@ from app.models import Database,db,DES,Table,Columns,TableVacuate
8 import uuid 8 import uuid
9 from . import database_test 9 from . import database_test
10 # from app.util import open_pg_data_source 10 # from app.util import open_pg_data_source
11 -from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn,Feature 11 +from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn,Feature,Geometry
12 from sqlalchemy.orm import Session 12 from sqlalchemy.orm import Session
13 from sqlalchemy import create_engine 13 from sqlalchemy import create_engine
14 from sqlalchemy.orm import sessionmaker 14 from sqlalchemy.orm import sessionmaker
15 from app.util.component.ApiTemplate import ApiTemplate 15 from app.util.component.ApiTemplate import ApiTemplate
16 from app.util.component.PGUtil import PGUtil 16 from app.util.component.PGUtil import PGUtil
  17 +from app.util.component.SQLUtil import SQLUtil
17 from app.util.component.GeometryAdapter import GeometryAdapter 18 from app.util.component.GeometryAdapter import GeometryAdapter
  19 +from app.util.component.StructuredPrint import StructurePrint
18 class Api(ApiTemplate): 20 class Api(ApiTemplate):
19 - api_name = "数据库注册" 21 + api_name = "注册数据库"
20 def process(self): 22 def process(self):
21 res ={} 23 res ={}
22 res["result"] = False 24 res["result"] = False
@@ -29,7 +31,7 @@ class Api(ApiTemplate): @@ -29,7 +31,7 @@ class Api(ApiTemplate):
29 encryption = int(self.para.get("encryption","0")) 31 encryption = int(self.para.get("encryption","0"))
30 if encryption: 32 if encryption:
31 passwd = DES.decode(passwd) 33 passwd = DES.decode(passwd)
32 - 34 +
33 sqlalchemy_uri = "postgresql://{}:{}@{}:{}/{}".format(user,passwd,host,port,database) 35 sqlalchemy_uri = "postgresql://{}:{}@{}:{}/{}".format(user,passwd,host,port,database)
34 connectsrt = "hostaddr={} port={} dbname='{}' user='{}' password='{}'".format(host,port,database,user,passwd) 36 connectsrt = "hostaddr={} port={} dbname='{}' user='{}' password='{}'".format(host,port,database,user,passwd)
35 37
@@ -87,26 +89,29 @@ class Api(ApiTemplate): @@ -87,26 +89,29 @@ class Api(ApiTemplate):
87 89
88 def register_table(self,database): 90 def register_table(self,database):
89 this_time = datetime.datetime.now() 91 this_time = datetime.datetime.now()
  92 +
90 pg_ds: DataSource = PGUtil.open_pg_data_source(1, DES.decode(database.sqlalchemy_uri)) 93 pg_ds: DataSource = PGUtil.open_pg_data_source(1, DES.decode(database.sqlalchemy_uri))
  94 + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(database.sqlalchemy_uri))
91 95
92 # 注册空间表 96 # 注册空间表
93 - spatial_table_name,tables = self.register_spatial_table(pg_ds, database, this_time) 97 + spatial_table_name,tables = self.register_spatial_table(pg_ds, database, this_time,db_tuple)
94 98
95 #注册抽稀表 99 #注册抽稀表
96 - self.regiser_vacuate_talbe(pg_ds,tables) 100 + self.regiser_vacuate_table(pg_ds,tables,db_tuple)
97 101
98 #注册普通表 102 #注册普通表
99 - self.register_common_table(this_time,database,spatial_table_name) 103 + self.register_common_table(this_time,database,spatial_table_name,db_tuple)
100 104
101 pg_ds.Destroy() 105 pg_ds.Destroy()
102 106
103 107
104 - def register_spatial_table(self,pg_ds,database,this_time): 108 + def register_spatial_table(self,pg_ds,database,this_time,db_tuple):
105 spatial_table_name =[] 109 spatial_table_name =[]
106 tables=[] 110 tables=[]
107 for i in range(pg_ds.GetLayerCount()): 111 for i in range(pg_ds.GetLayerCount()):
108 layer: Layer = pg_ds.GetLayer(i) 112 layer: Layer = pg_ds.GetLayer(i)
109 l_name = layer.GetName() 113 l_name = layer.GetName()
  114 +
110 # 只注册public的空间表,其他表空间的表名会有. 115 # 只注册public的空间表,其他表空间的表名会有.
111 if layer.GetName().__contains__("."): 116 if layer.GetName().__contains__("."):
112 continue 117 continue
@@ -116,9 +121,15 @@ class Api(ApiTemplate): @@ -116,9 +121,15 @@ class Api(ApiTemplate):
116 spatial_table_name.append(layer.GetName()) 121 spatial_table_name.append(layer.GetName())
117 continue 122 continue
118 123
  124 + # 没有权限的表跳过
  125 + if not PGUtil.check_table_privilege(l_name,"SELECT",db_tuple[0],pg_ds):
  126 + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0],l_name),"warn")
  127 + continue
  128 +
119 # 范围统计和数量统计以100w为界限 129 # 范围统计和数量统计以100w为界限
120 query_count_layer: Layer = pg_ds.ExecuteSQL( 130 query_count_layer: Layer = pg_ds.ExecuteSQL(
121 '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(l_name)) 131 '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(l_name))
  132 +
122 feature_count = query_count_layer.GetFeature(0).GetField("ec") 133 feature_count = query_count_layer.GetFeature(0).GetField("ec")
123 # 要素少于100w可以精确统计 134 # 要素少于100w可以精确统计
124 if feature_count < 1000000: 135 if feature_count < 1000000:
@@ -137,11 +148,13 @@ class Api(ApiTemplate): @@ -137,11 +148,13 @@ class Api(ApiTemplate):
137 148
138 table_guid = uuid.uuid1().__str__() 149 table_guid = uuid.uuid1().__str__()
139 150
  151 + geom_type = GeometryAdapter.get_geometry_type(layer)
  152 +
140 table = Table(guid=table_guid, 153 table = Table(guid=table_guid,
141 database_guid=database.guid, 154 database_guid=database.guid,
142 # alias=layer.GetName(), 155 # alias=layer.GetName(),
143 name=layer.GetName(), create_time=this_time, update_time=this_time, 156 name=layer.GetName(), create_time=this_time, update_time=this_time,
144 - table_type=GeometryAdapter.get_table_type(GeometryAdapter.get_geometry_type(layer)), 157 + table_type=GeometryAdapter.get_table_type(geom_type),
145 extent=extent, 158 extent=extent,
146 feature_count=feature_count 159 feature_count=feature_count
147 ) 160 )
@@ -164,19 +177,26 @@ class Api(ApiTemplate): @@ -164,19 +177,26 @@ class Api(ApiTemplate):
164 return spatial_table_name,tables 177 return spatial_table_name,tables
165 178
166 179
167 - def register_common_table(self,this_time,database,spatial_table_name): 180 + def register_common_table(self,this_time,database,spatial_table_name,db_tuple):
168 # 注册普通表 181 # 注册普通表
169 db_session: Session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri)) 182 db_session: Session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri))
170 183
171 # 只注册public中的表 184 # 只注册public中的表
172 result = db_session.execute( 185 result = db_session.execute(
173 "select relname as tabname from pg_class c where relkind = 'r' and relnamespace=2200 and relname not like 'pg_%' and relname not like 'sql_%' order by relname").fetchall() 186 "select relname as tabname from pg_class c where relkind = 'r' and relnamespace=2200 and relname not like 'pg_%' and relname not like 'sql_%' order by relname").fetchall()
  187 +
174 for re in result: 188 for re in result:
175 table_name = re[0] 189 table_name = re[0]
176 if table_name not in spatial_table_name: 190 if table_name not in spatial_table_name:
177 191
  192 + # 没有权限的表跳过
  193 + if not SQLUtil.check_table_privilege(table_name, "SELECT", db_tuple[0], db_session):
  194 + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0],table_name), "warn")
  195 + continue
  196 +
178 table_guid = uuid.uuid1().__str__() 197 table_guid = uuid.uuid1().__str__()
179 - count = db_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0] 198 +
  199 + count = SQLUtil.get_table_count(table_name,db_session)
180 200
181 table = Table(guid=table_guid, 201 table = Table(guid=table_guid,
182 database_guid=database.guid, 202 database_guid=database.guid,
@@ -209,15 +229,26 @@ class Api(ApiTemplate): @@ -209,15 +229,26 @@ class Api(ApiTemplate):
209 column = Columns(guid=uuid.uuid1().__str__(), table_guid=table_guid, 229 column = Columns(guid=uuid.uuid1().__str__(), table_guid=table_guid,
210 name=col[1], create_time=this_time, update_time=this_time) 230 name=col[1], create_time=this_time, update_time=this_time)
211 db.session.add(column) 231 db.session.add(column)
  232 + db_session.commit()
212 db_session.close() 233 db_session.close()
213 234
214 - def regiser_vacuate_talbe(self,pg_ds,tables): 235 +
  236 + def regiser_vacuate_table(self,pg_ds,tables,db_tuple):
215 237
216 # 注册抽稀表 238 # 注册抽稀表
217 for i in range(pg_ds.GetLayerCount()): 239 for i in range(pg_ds.GetLayerCount()):
218 layer:Layer = pg_ds.GetLayer(i) 240 layer:Layer = pg_ds.GetLayer(i)
219 l_name = layer.GetName() 241 l_name = layer.GetName()
  242 +
  243 +
  244 +
220 if l_name.__contains__("_vacuate_"): 245 if l_name.__contains__("_vacuate_"):
  246 +
  247 + # 没有权限的表跳过
  248 + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds):
  249 + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn")
  250 + continue
  251 +
221 base_layer_name=l_name.split("_vacuate_")[0] 252 base_layer_name=l_name.split("_vacuate_")[0]
222 level = l_name.split("_")[-2] 253 level = l_name.split("_")[-2]
223 pixel_distance_str: str ="0" 254 pixel_distance_str: str ="0"
@@ -227,15 +258,17 @@ class Api(ApiTemplate): @@ -227,15 +258,17 @@ class Api(ApiTemplate):
227 pixel_distance_str="0.{}".format(pixel_distance_str) 258 pixel_distance_str="0.{}".format(pixel_distance_str)
228 except: 259 except:
229 pass 260 pass
230 - base_table = [table for table in tables if table.name.__eq__(base_layer_name)][0]  
231 - table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(),  
232 - table_guid=base_table.guid,  
233 - level=level,  
234 - name=l_name,  
235 - pixel_distance=float(pixel_distance_str)) 261 + base_table = [table for table in tables if table.name.__eq__(base_layer_name)]
  262 + if base_table:
  263 + base_table = base_table[0]
  264 + table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(),
  265 + table_guid=base_table.guid,
  266 + level=level,
  267 + name=l_name,
  268 + pixel_distance=float(pixel_distance_str))
236 269
237 - Table.query.filter_by(guid=base_table.guid).update({"is_vacuate": 1})  
238 - db.session.add(table_vacuate) 270 + Table.query.filter_by(guid=base_table.guid).update({"is_vacuate":1})
  271 + db.session.add(table_vacuate)
239 272
240 273
241 274
@@ -247,7 +280,6 @@ class Api(ApiTemplate): @@ -247,7 +280,6 @@ class Api(ApiTemplate):
247 engine = create_engine(sqlachemy_uri) 280 engine = create_engine(sqlachemy_uri)
248 system_session = sessionmaker(bind=engine)() 281 system_session = sessionmaker(bind=engine)()
249 system_session.execute(test_sql).fetchone() 282 system_session.execute(test_sql).fetchone()
250 -  
251 except: 283 except:
252 check = False 284 check = False
253 finally: 285 finally:
@@ -281,10 +313,6 @@ class Api(ApiTemplate): @@ -281,10 +313,6 @@ class Api(ApiTemplate):
281 {"name": "alias", 313 {"name": "alias",
282 "in": "formData", 314 "in": "formData",
283 "type": "string","description":"数据库别名","required": "true"}, 315 "type": "string","description":"数据库别名","required": "true"},
284 -  
285 - {"name": "encryption",  
286 - "in": "formData",  
287 - "type": "integer", "description": "密码是否加密", "enum": [0,1]},  
288 ], 316 ],
289 "responses":{ 317 "responses":{
290 200:{ 318 200:{
@@ -8,28 +8,28 @@ from app.models import * @@ -8,28 +8,28 @@ from app.models import *
8 8
9 import traceback 9 import traceback
10 10
11 -from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn  
12 -from osgeo import gdal ,ogr 11 +from osgeo.ogr import DataSource,Layer,FeatureDefn,FieldDefn,Feature
  12 +from osgeo import gdal,ogr
13 import os 13 import os
14 import uuid 14 import uuid
15 import configure 15 import configure
16 from app.util.component.ApiTemplate import ApiTemplate 16 from app.util.component.ApiTemplate import ApiTemplate
17 from app.util.component.PGUtil import PGUtil 17 from app.util.component.PGUtil import PGUtil
18 from app.util.component.ZipUtil import ZipUtil 18 from app.util.component.ZipUtil import ZipUtil
  19 +
19 class Api(ApiTemplate): 20 class Api(ApiTemplate):
20 21
21 - api_name = "下载数据"  
22 def process(self): 22 def process(self):
23 #获取参数 23 #获取参数
24 24
25 #返回结果 25 #返回结果
26 - res={} 26 + result={}
27 #设置编码 27 #设置编码
28 encoding = self.para.get("encoding") 28 encoding = self.para.get("encoding")
29 if encoding: 29 if encoding:
30 gdal.SetConfigOption("SHAPE_ENCODING",encoding) 30 gdal.SetConfigOption("SHAPE_ENCODING",encoding)
31 else: 31 else:
32 - gdal.SetConfigOption("SHAPE_ENCODING", "GBK") 32 + gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8")
33 33
34 ds:DataSource = None 34 ds:DataSource = None
35 try: 35 try:
@@ -38,6 +38,7 @@ class Api(ApiTemplate): @@ -38,6 +38,7 @@ class Api(ApiTemplate):
38 database = Database.query.filter_by(guid=database_guid).one_or_none() 38 database = Database.query.filter_by(guid=database_guid).one_or_none()
39 if not database: 39 if not database:
40 raise Exception("数据库不存在!") 40 raise Exception("数据库不存在!")
  41 +
41 42
42 ds:DataSource = PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri)) 43 ds:DataSource = PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri))
43 44
@@ -49,16 +50,16 @@ class Api(ApiTemplate): @@ -49,16 +50,16 @@ class Api(ApiTemplate):
49 if download_type.__eq__("gdb"): 50 if download_type.__eq__("gdb"):
50 data = self.download_gdb(table_names, ds,database_guid) 51 data = self.download_gdb(table_names, ds,database_guid)
51 52
52 - res["data"] = data  
53 - res["result"] = True 53 + result["data"] = data
  54 + result["state"] = 1
54 except Exception as e: 55 except Exception as e:
55 print(traceback.format_exc()) 56 print(traceback.format_exc())
56 - res["msg"]= e.__str__()  
57 - res["result"]=False 57 + result["message"]= e.__str__()
  58 + result["state"]=-1
58 finally: 59 finally:
59 if ds: 60 if ds:
60 ds.Destroy() 61 ds.Destroy()
61 - return res 62 + return result
62 63
63 64
64 def download_shp(self,table_names,ds): 65 def download_shp(self,table_names,ds):
@@ -77,9 +78,23 @@ class Api(ApiTemplate): @@ -77,9 +78,23 @@ class Api(ApiTemplate):
77 dirpath = os.path.join(parent, "file_tmp", uuid_) 78 dirpath = os.path.join(parent, "file_tmp", uuid_)
78 os.makedirs(dirpath) 79 os.makedirs(dirpath)
79 data_source: DataSource = driver.CreateDataSource(dirpath + "/{}.shp".format(table_name)) 80 data_source: DataSource = driver.CreateDataSource(dirpath + "/{}.shp".format(table_name))
80 - data_source.CopyLayer(layer, table_name) 81 + # data_source.CopyLayer(layer, table_name)
  82 +
  83 +
  84 + fid = layer.GetFIDColumn()
  85 + pg_layer: Layer = data_source.CreateLayer(table_name, layer.GetSpatialRef(), layer.GetGeomType())
  86 + schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)]
  87 +
  88 + pg_layer.CreateFields(schema)
  89 + layer.ResetReading()
  90 + for feature in layer:
  91 + pg_layer.CreateFeature(feature)
  92 +
81 data_source.Destroy() 93 data_source.Destroy()
  94 +
  95 +
82 ZipUtil.create_zip(os.path.join(parent, "file_tmp", table_name+"_"+uuid_) + ".zip", [dirpath]) 96 ZipUtil.create_zip(os.path.join(parent, "file_tmp", table_name+"_"+uuid_) + ".zip", [dirpath])
  97 +
83 return "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(table_name+"_"+uuid_ + ".zip") 98 return "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(table_name+"_"+uuid_ + ".zip")
84 99
85 100
@@ -114,13 +129,32 @@ class Api(ApiTemplate): @@ -114,13 +129,32 @@ class Api(ApiTemplate):
114 # if not table_alias: 129 # if not table_alias:
115 # table_alias = table_name 130 # table_alias = table_name
116 # table_name = "table{}".format(table_name.__hash__()) 131 # table_name = "table{}".format(table_name.__hash__())
117 -  
118 - gdb_ds.CopyLayer(layer, table_name,["LAYER_ALIAS={}".format(table_alias)]) 132 +
  133 + fid = layer.GetFIDColumn()
  134 + pg_layer: Layer = gdb_ds.CreateLayer(table_name, layer.GetSpatialRef(), layer.GetGeomType(),["LAYER_ALIAS={}".format(table_alias)])
  135 + schema = [sche for sche in layer.schema if not sche.name.__eq__(fid)]
  136 + # schema = layer.schema
  137 + pg_layer.CreateFields(schema)
  138 +
  139 +
  140 + # gdb 不支持fid=0的要素,所以识别到后要+1
  141 + offset = 0
  142 + f1:Feature = layer.GetNextFeature()
  143 + if f1:
  144 + if f1.GetFID().__eq__(0):
  145 + offset = 1
  146 + layer.ResetReading()
  147 + for feature in layer:
  148 + feature.SetFID(feature.GetFID()+offset)
  149 + pg_layer.CreateFeature(feature)
  150 +
  151 +
  152 + # gdb_ds.CopyLayer(layer, table_name,["LAYER_ALIAS={}".format(table_alias)])
119 153
120 gdb_ds.Destroy() 154 gdb_ds.Destroy()
121 ZipUtil.create_zip(gdb_path + ".zip", [gdb_path]) 155 ZipUtil.create_zip(gdb_path + ".zip", [gdb_path])
122 data.append({"name": ",".join(table_names), "download_url": "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(uuid_+".gdb" + ".zip")}) 156 data.append({"name": ",".join(table_names), "download_url": "http://" + configure.deploy_ip_host + "/API/IO/Download/{}".format(uuid_+".gdb" + ".zip")})
123 - 157 +
124 158
125 return data 159 return data
126 160
@@ -18,6 +18,10 @@ from . import table_refresh @@ -18,6 +18,10 @@ from . import table_refresh
18 from . import table_delete 18 from . import table_delete
19 from . import table_view 19 from . import table_view
20 from . import table_vacuate 20 from . import table_vacuate
  21 +from . import table_vacuate_one
  22 +from . import table_vacuate_info
  23 +from . import table_vacuate_ref
  24 +from . import table_vacuate_delete
21 class DataManager(BlueprintApi): 25 class DataManager(BlueprintApi):
22 26
23 bp = Blueprint("DataManager", __name__, url_prefix="/API/Manager") 27 bp = Blueprint("DataManager", __name__, url_prefix="/API/Manager")
@@ -106,4 +110,41 @@ class DataManager(BlueprintApi): @@ -106,4 +110,41 @@ class DataManager(BlueprintApi):
106 """ 110 """
107 数据抽稀 111 数据抽稀
108 """ 112 """
109 - return table_vacuate.Api().result  
  113 + return table_vacuate.Api().result
  114 +
  115 + @staticmethod
  116 + @bp.route('/TableVacuateOne', methods=['POST'])
  117 + @swag_from(table_vacuate_one.Api.api_doc)
  118 + def api_table_vacuate_one():
  119 + """
  120 + 单独数据抽稀
  121 + """
  122 + return table_vacuate_one.Api().result
  123 +
  124 +
  125 + @staticmethod
  126 + @bp.route('/TableVacuateInfo', methods=['POST'])
  127 + @swag_from(table_vacuate_info.Api.api_doc)
  128 + def api_table_vacuate_info():
  129 + """
  130 + 数据抽稀情况
  131 + """
  132 + return table_vacuate_info.Api().result
  133 +
  134 + @staticmethod
  135 + @bp.route('/TableVacuateRef', methods=['POST'])
  136 + @swag_from(table_vacuate_ref.Api.api_doc)
  137 + def api_table_vacuate_ref():
  138 + """
  139 + 数据抽稀参考
  140 + """
  141 + return table_vacuate_ref.Api().result
  142 +
  143 + @staticmethod
  144 + @bp.route('/TableVacuateDelete', methods=['POST'])
  145 + @swag_from(table_vacuate_delete.Api.api_doc)
  146 + def api_table_vacuate_delete():
  147 + """
  148 + 数据抽稀删除
  149 + """
  150 + return table_vacuate_delete.Api().result
@@ -40,6 +40,10 @@ class Api(ApiTemplate): @@ -40,6 +40,10 @@ class Api(ApiTemplate):
40 tables = Table.query.order_by(Table.update_time.desc(),Table.name) 40 tables = Table.query.order_by(Table.update_time.desc(),Table.name)
41 else: 41 else:
42 tables = Table.query.order_by(Table.name) 42 tables = Table.query.order_by(Table.name)
  43 +
  44 + #过滤spatial_ref_sys
  45 + tables = tables.filter(Table.name.notin_(["spatial_ref_sys"]))
  46 +
43 if database_guid: 47 if database_guid:
44 tables = tables.filter_by(database_guid=database_guid) 48 tables = tables.filter_by(database_guid=database_guid)
45 if catalog_guid: 49 if catalog_guid:
@@ -13,7 +13,7 @@ import datetime @@ -13,7 +13,7 @@ import datetime
13 import uuid 13 import uuid
14 14
15 from sqlalchemy.orm import Session 15 from sqlalchemy.orm import Session
16 - 16 +from app.util.component.SQLUtil import SQLUtil
17 from app.util.component.PGUtil import PGUtil 17 from app.util.component.PGUtil import PGUtil
18 from app.util.component.ModelVisitor import ModelVisitor 18 from app.util.component.ModelVisitor import ModelVisitor
19 from app.util.component.StructuredPrint import StructurePrint 19 from app.util.component.StructuredPrint import StructurePrint
@@ -70,6 +70,8 @@ class Api(ApiTemplate): @@ -70,6 +70,8 @@ class Api(ApiTemplate):
70 data_session=None 70 data_session=None
71 result = {} 71 result = {}
72 sys_session = None 72 sys_session = None
  73 + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(database.sqlalchemy_uri))
  74 +
73 try: 75 try:
74 sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) 76 sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI)
75 77
@@ -89,16 +91,16 @@ class Api(ApiTemplate): @@ -89,16 +91,16 @@ class Api(ApiTemplate):
89 91
90 # 更新空间表 92 # 更新空间表
91 # 增加表 93 # 增加表
92 - db_tables_names = self.add_spatail_table(database, pg_ds, sys_session,spatial_tables_names, this_time)# 实体库中空间表名 94 + db_tables_names = self.add_spatail_table(database, pg_ds, sys_session,spatial_tables_names, this_time,db_tuple)# 实体库中空间表名
93 95
94 # 删除/修改表 96 # 删除/修改表
95 - self.edit_spatial_table(pg_ds, sys_session,spatial_tables, db_tables_names, this_time) 97 + self.edit_spatial_table(pg_ds, sys_session,spatial_tables, db_tables_names, this_time,db_tuple)
96 98
97 # 空间表处理完毕 99 # 空间表处理完毕
98 sys_session.commit() 100 sys_session.commit()
99 101
100 # 处理抽稀表 102 # 处理抽稀表
101 - self.deal_vacuate_table(pg_ds,sys_session, database.guid) 103 + self.deal_vacuate_table(pg_ds,sys_session, database.guid,db_tuple)
102 104
103 # 空间表处理完毕 105 # 空间表处理完毕
104 sys_session.commit() 106 sys_session.commit()
@@ -133,11 +135,11 @@ class Api(ApiTemplate): @@ -133,11 +135,11 @@ class Api(ApiTemplate):
133 # 增加新普通表 135 # 增加新普通表
134 136
135 self.add_common_table(data_session, sys_session, database_guid, real_common_tables_name, origin_common_tables_name, 137 self.add_common_table(data_session, sys_session, database_guid, real_common_tables_name, origin_common_tables_name,
136 - this_time) 138 + this_time,db_tuple)
137 139
138 # 删除、修改普通表 140 # 删除、修改普通表
139 self.edit_common_table(data_session,sys_session, database_guid, real_common_tables_name, origin_common_tables_name, 141 self.edit_common_table(data_session,sys_session, database_guid, real_common_tables_name, origin_common_tables_name,
140 - this_time) 142 + this_time,db_tuple)
141 143
142 sys_session.commit() 144 sys_session.commit()
143 result["data"] = "刷新数据成功!" 145 result["data"] = "刷新数据成功!"
@@ -168,7 +170,7 @@ class Api(ApiTemplate): @@ -168,7 +170,7 @@ class Api(ApiTemplate):
168 sys_session.close() 170 sys_session.close()
169 return result 171 return result
170 172
171 - def add_spatail_table(self,database,pg_ds,sys_session,spatial_tables_names,this_time): 173 + def add_spatail_table(self,database,pg_ds,sys_session,spatial_tables_names,this_time,db_tuple):
172 ''' 174 '''
173 注册新增空间表 175 注册新增空间表
174 :param database: 176 :param database:
@@ -196,10 +198,17 @@ class Api(ApiTemplate): @@ -196,10 +198,17 @@ class Api(ApiTemplate):
196 if layer.GetName().__contains__("_vacuate_"): 198 if layer.GetName().__contains__("_vacuate_"):
197 continue 199 continue
198 200
  201 + # 没有权限的表跳过
  202 + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds):
  203 + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn")
  204 + continue
  205 +
  206 +
199 # 范围统计和数量统计以100w为界限 207 # 范围统计和数量统计以100w为界限
200 query_count_layer: Layer = pg_ds.ExecuteSQL( 208 query_count_layer: Layer = pg_ds.ExecuteSQL(
201 '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format( 209 '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(
202 l_name)) 210 l_name))
  211 +
203 feature_count = query_count_layer.GetFeature(0).GetField("ec") 212 feature_count = query_count_layer.GetFeature(0).GetField("ec")
204 # 要素少于100w可以精确统计 213 # 要素少于100w可以精确统计
205 if feature_count < 1000000: 214 if feature_count < 1000000:
@@ -218,12 +227,14 @@ class Api(ApiTemplate): @@ -218,12 +227,14 @@ class Api(ApiTemplate):
218 227
219 StructurePrint.print("空间表增加!") 228 StructurePrint.print("空间表增加!")
220 229
  230 + geom_type = GeometryAdapter.get_geometry_type(layer)
  231 +
221 table_guid = uuid.uuid1().__str__() 232 table_guid = uuid.uuid1().__str__()
222 table = Table(guid=table_guid, 233 table = Table(guid=table_guid,
223 database_guid=database.guid, 234 database_guid=database.guid,
224 # alias=layer.GetName(), 235 # alias=layer.GetName(),
225 name=layer.GetName(), create_time=this_time, update_time=this_time, 236 name=layer.GetName(), create_time=this_time, update_time=this_time,
226 - table_type=GeometryAdapter.get_table_type(GeometryAdapter.get_geometry_type(layer)), 237 + table_type=GeometryAdapter.get_table_type(geom_type),
227 extent=extent, 238 extent=extent,
228 feature_count=feature_count 239 feature_count=feature_count
229 ) 240 )
@@ -240,7 +251,7 @@ class Api(ApiTemplate): @@ -240,7 +251,7 @@ class Api(ApiTemplate):
240 sys_session.add(column) 251 sys_session.add(column)
241 return db_tables_names 252 return db_tables_names
242 253
243 - def deal_vacuate_table(self,pg_ds,sys_session,database_guid): 254 + def deal_vacuate_table(self,pg_ds,sys_session,database_guid,db_tuple):
244 255
245 256
246 for i in range(pg_ds.GetLayerCount()): 257 for i in range(pg_ds.GetLayerCount()):
@@ -255,6 +266,10 @@ class Api(ApiTemplate): @@ -255,6 +266,10 @@ class Api(ApiTemplate):
255 if layer.GetName().__contains__("_vacuate_"): 266 if layer.GetName().__contains__("_vacuate_"):
256 l_name = layer.GetName() 267 l_name = layer.GetName()
257 268
  269 + # 没有权限的表跳过
  270 + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds):
  271 + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn")
  272 + continue
258 273
259 base_layer_name = l_name.split("_vacuate_")[0] 274 base_layer_name = l_name.split("_vacuate_")[0]
260 level = l_name.split("_")[-2] 275 level = l_name.split("_")[-2]
@@ -283,7 +298,9 @@ class Api(ApiTemplate): @@ -283,7 +298,9 @@ class Api(ApiTemplate):
283 298
284 299
285 300
286 - def edit_spatial_table(self,pg_ds,sys_session,spatial_tables,db_tables_names,this_time): 301 + def edit_spatial_table(self,pg_ds,sys_session,spatial_tables,db_tables_names,this_time,db_tuple):
  302 +
  303 +
287 304
288 for table in spatial_tables: 305 for table in spatial_tables:
289 306
@@ -303,6 +320,12 @@ class Api(ApiTemplate): @@ -303,6 +320,12 @@ class Api(ApiTemplate):
303 if layer.GetName().__contains__("_vacuate_"): 320 if layer.GetName().__contains__("_vacuate_"):
304 continue 321 continue
305 322
  323 + # 没有权限的表跳过
  324 + if not PGUtil.check_table_privilege(l_name, "SELECT", db_tuple[0], pg_ds):
  325 + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], l_name), "warn")
  326 + sys_session.delete(table)
  327 + continue
  328 +
306 columns = table.relate_columns 329 columns = table.relate_columns
307 columns_names = [column.name for column in columns] 330 columns_names = [column.name for column in columns]
308 feature_defn: FeatureDefn = layer.GetLayerDefn() 331 feature_defn: FeatureDefn = layer.GetLayerDefn()
@@ -357,11 +380,18 @@ class Api(ApiTemplate): @@ -357,11 +380,18 @@ class Api(ApiTemplate):
357 "extent": extent}) 380 "extent": extent})
358 381
359 382
360 - def add_common_table(self,data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time): 383 + def add_common_table(self,data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time,db_tuple):
361 for table_name in real_common_tables_name: 384 for table_name in real_common_tables_name:
362 if table_name not in origin_common_tables_name: 385 if table_name not in origin_common_tables_name:
363 StructurePrint.print("{}非空间表增加!".format(table_name)) 386 StructurePrint.print("{}非空间表增加!".format(table_name))
364 table_guid = uuid.uuid1().__str__() 387 table_guid = uuid.uuid1().__str__()
  388 +
  389 +
  390 + # 没有权限的表跳过
  391 + if not SQLUtil.check_table_privilege(table_name, "SELECT", db_tuple[0], data_session):
  392 + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], table_name), "warn")
  393 + continue
  394 +
365 count = data_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0] 395 count = data_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0]
366 396
367 table = Table(guid=table_guid, 397 table = Table(guid=table_guid,
@@ -402,7 +432,7 @@ class Api(ApiTemplate): @@ -402,7 +432,7 @@ class Api(ApiTemplate):
402 for table in tables: 432 for table in tables:
403 sys_session.delete(table) 433 sys_session.delete(table)
404 434
405 - def edit_common_table(self,data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time): 435 + def edit_common_table(self,data_session,sys_session,database_guid,real_common_tables_name,origin_common_tables_name,this_time,db_tuple):
406 for table_name in origin_common_tables_name: 436 for table_name in origin_common_tables_name:
407 tables = sys_session.query(Table).filter_by(name=table_name).filter_by(database_guid=database_guid).all() 437 tables = sys_session.query(Table).filter_by(name=table_name).filter_by(database_guid=database_guid).all()
408 for table in tables: 438 for table in tables:
@@ -411,6 +441,13 @@ class Api(ApiTemplate): @@ -411,6 +441,13 @@ class Api(ApiTemplate):
411 sys_session.delete(table) 441 sys_session.delete(table)
412 # 修改表 442 # 修改表
413 else: 443 else:
  444 +
  445 + # 没有权限的表删除
  446 + if not SQLUtil.check_table_privilege(table_name, "SELECT", db_tuple[0], data_session):
  447 + StructurePrint.print("用户{}对表{}没有select权限!".format(db_tuple[0], table_name), "warn")
  448 + sys_session.delete(table)
  449 + continue
  450 +
414 columns = table.relate_columns 451 columns = table.relate_columns
415 columns_names = [column.name for column in columns] 452 columns_names = [column.name for column in columns]
416 453
@@ -448,15 +485,15 @@ class Api(ApiTemplate): @@ -448,15 +485,15 @@ class Api(ApiTemplate):
448 sys_session.delete(column) 485 sys_session.delete(column)
449 486
450 # 修改要素量 487 # 修改要素量
451 - sql = 'select count(*) from "{}"'.format(table_name) 488 + # sql = 'select count(*) from "{}"'.format(table_name)
  489 + # count = data_session.execute(sql).fetchone()[0]
  490 +
  491 + count = SQLUtil.get_table_count(table_name,data_session)
452 492
453 - count = data_session.execute(sql).fetchone()[0]  
454 if not table.feature_count.__eq__(count): 493 if not table.feature_count.__eq__(count):
455 StructurePrint.print("{}表要素变化!".format(table_name)) 494 StructurePrint.print("{}表要素变化!".format(table_name))
456 sys_session.query(Table).filter_by(guid=table.guid).update({"feature_count": count}) 495 sys_session.query(Table).filter_by(guid=table.guid).update({"feature_count": count})
457 496
458 -  
459 -  
460 497
461 api_doc={ 498 api_doc={
462 "tags":["管理接口"], 499 "tags":["管理接口"],
@@ -5,19 +5,23 @@ @@ -5,19 +5,23 @@
5 5
6 import datetime 6 import datetime
7 import traceback 7 import traceback
8 -from app.models import Table, Database, DES,Task,db 8 +from app.models import Table, Database, DES,Task,db,TableVacuate
9 9
10 from sqlalchemy.engine import ResultProxy 10 from sqlalchemy.engine import ResultProxy
11 from app.util.component.ApiTemplate import ApiTemplate 11 from app.util.component.ApiTemplate import ApiTemplate
12 from app.util.component.PGUtil import PGUtil 12 from app.util.component.PGUtil import PGUtil
13 from app.util.component.EntryDataVacuate import VacuateProcess,ThisTask,Process 13 from app.util.component.EntryDataVacuate import VacuateProcess,ThisTask,Process
  14 +from app.util.component.StructuredPrint import StructurePrint
  15 +from app.util.component.PGUtil import PGUtil
14 import multiprocessing 16 import multiprocessing
15 import uuid 17 import uuid
16 import configure 18 import configure
17 -from osgeo.ogr import DataSource 19 +from osgeo.ogr import DataSource,Layer
18 20
19 -class Api(ApiTemplate): 21 +from .table_vacuate_ref import Api as RefApi
20 22
  23 +class Api(ApiTemplate):
  24 + api_name = "数据抽稀"
21 def process(self): 25 def process(self):
22 26
23 res = {} 27 res = {}
@@ -26,15 +30,21 @@ class Api(ApiTemplate): @@ -26,15 +30,21 @@ class Api(ApiTemplate):
26 try: 30 try:
27 table_guid = self.para.get("guid") 31 table_guid = self.para.get("guid")
28 table: Table = Table.query.filter_by(guid=table_guid).one_or_none() 32 table: Table = Table.query.filter_by(guid=table_guid).one_or_none()
  33 +
29 if not table: 34 if not table:
30 raise Exception("数据不存在!") 35 raise Exception("数据不存在!")
31 36
32 - # 判断图层是否存在  
33 -  
34 pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri)) 37 pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri))
35 layer = pg_ds.GetLayerByName(table.name) 38 layer = pg_ds.GetLayerByName(table.name)
  39 + # 判断图层是否存在
36 if not layer: 40 if not layer:
37 raise Exception("图层不存在!") 41 raise Exception("图层不存在!")
  42 +
  43 + # 判断用户权限
  44 + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(table.relate_database.sqlalchemy_uri))
  45 + if not PGUtil.check_table_privilege(table.name,"SELECT",db_tuple[0],pg_ds):
  46 + raise Exception("用户{}对表{}没有select权限!".format(db_tuple[0],table.name))
  47 +
38 if pg_ds: 48 if pg_ds:
39 pg_ds.Destroy() 49 pg_ds.Destroy()
40 50
@@ -46,17 +56,22 @@ class Api(ApiTemplate): @@ -46,17 +56,22 @@ class Api(ApiTemplate):
46 res["result"] = False 56 res["result"] = False
47 res["msg"] = "非空间表!" 57 res["msg"] = "非空间表!"
48 return res 58 return res
  59 +
49 # if table.is_vacuate==1: 60 # if table.is_vacuate==1:
50 # res["state"] = -1 61 # res["state"] = -1
51 # res["message"] = "已精化!" 62 # res["message"] = "已精化!"
52 # return res 63 # return res
53 64
54 65
  66 +
55 # 初始化task 67 # 初始化task
56 task_guid = uuid.uuid1().__str__() 68 task_guid = uuid.uuid1().__str__()
57 vacuate_process = multiprocessing.Process(target=self.task,args=(table,task_guid)) 69 vacuate_process = multiprocessing.Process(target=self.task,args=(table,task_guid))
58 vacuate_process.start() 70 vacuate_process.start()
59 71
  72 + ref_api = RefApi()
  73 + ref_api.para["guid"] = table_guid
  74 + ref_grids = ref_api.process()["data"]
60 75
61 task = Task(guid=task_guid, 76 task = Task(guid=task_guid,
62 name="{}精化".format(table.name), 77 name="{}精化".format(table.name),
@@ -67,12 +82,15 @@ class Api(ApiTemplate): @@ -67,12 +82,15 @@ class Api(ApiTemplate):
67 creator=self.para.get("creator"), 82 creator=self.para.get("creator"),
68 file_name=None, 83 file_name=None,
69 database_guid=table.database_guid, 84 database_guid=table.database_guid,
70 - process="精化中") 85 + process="精化中",
  86 + parameter=",".join([str(x) for x in ref_grids]))
  87 +
71 db.session.add(task) 88 db.session.add(task)
72 db.session.commit() 89 db.session.commit()
73 res["msg"] = "图层抽稀已提交!" 90 res["msg"] = "图层抽稀已提交!"
74 - res["data"] = table_guid 91 + res["data"] = task_guid
75 res["result"] = True 92 res["result"] = True
  93 +
76 except Exception as e: 94 except Exception as e:
77 raise e 95 raise e
78 finally: 96 finally:
@@ -87,23 +105,34 @@ class Api(ApiTemplate): @@ -87,23 +105,34 @@ class Api(ApiTemplate):
87 pg_ds = None 105 pg_ds = None
88 vacuate_process = None 106 vacuate_process = None
89 try: 107 try:
90 -  
91 - sys_session= PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI)  
92 - 108 + sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI)
93 sys_session.query(Table).filter_by(guid=table.guid).update( 109 sys_session.query(Table).filter_by(guid=table.guid).update(
94 {"is_vacuate": 2, "update_time": datetime.datetime.now()}) 110 {"is_vacuate": 2, "update_time": datetime.datetime.now()})
95 sys_session.commit() 111 sys_session.commit()
96 112
  113 +
97 database = sys_session.query(Database).filter_by(guid=table.database_guid).one_or_none() 114 database = sys_session.query(Database).filter_by(guid=table.database_guid).one_or_none()
98 pg_session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri)) 115 pg_session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri))
99 116
100 pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri)) 117 pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri))
101 118
  119 +
  120 + #删除原有数据
  121 + tvs = sys_session.query(TableVacuate).filter_by(table_guid=table.guid).all()
  122 + for tv in tvs :
  123 + sys_session.delete(tv)
  124 + # try:
  125 + # pg_ds.DeleteLayer(tv.name)
  126 + # except Exception as e :
  127 + # StructurePrint.print("抽稀图层不存在!","warn")
  128 +
102 # 创建抽稀过程 129 # 创建抽稀过程
103 options = ["OVERWRITE=yes", "GEOMETRY_NAME={}".format(PGUtil.get_geo_column(table.name,pg_session)), 130 options = ["OVERWRITE=yes", "GEOMETRY_NAME={}".format(PGUtil.get_geo_column(table.name,pg_session)),
104 "PRECISION=NO"] 131 "PRECISION=NO"]
  132 +
105 layer = pg_ds.GetLayerByName(table.name) 133 layer = pg_ds.GetLayerByName(table.name)
106 - vacuate_process = VacuateProcess(layer, table.name, options,database.sqlalchemy_uri) 134 +
  135 + vacuate_process:VacuateProcess = VacuateProcess(layer, table.name, options,database.sqlalchemy_uri)
107 136
108 137
109 for feature in layer: 138 for feature in layer:
@@ -112,14 +141,28 @@ class Api(ApiTemplate): @@ -112,14 +141,28 @@ class Api(ApiTemplate):
112 if geo is not None: 141 if geo is not None:
113 vacuate_process.vacuate(geo) 142 vacuate_process.vacuate(geo)
114 143
115 - sys_session.query(Task).filter_by(guid=task_guid).update({"state":1,"update_time":datetime.datetime.now()}) 144 +
  145 + #新增
  146 + for l in range(vacuate_process.max_level):
  147 + lev = vacuate_process.t_grid_size.index(vacuate_process.this_gridsize[l])
  148 +
  149 + table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(),
  150 + table_guid=table.guid,
  151 + level=lev,
  152 + name=vacuate_process.vacuate_layers[l].GetName(),
  153 + pixel_distance=vacuate_process.this_gridsize[l])
  154 + sys_session.add(table_vacuate)
  155 +
  156 + sys_session.query(Task).filter_by(guid=task_guid).update({"state":1,"update_time":datetime.datetime.now(),
  157 + "process": "精化完成"})
116 sys_session.query(Table).filter_by(guid=table.guid).update( 158 sys_session.query(Table).filter_by(guid=table.guid).update(
117 {"is_vacuate": 1, "update_time": datetime.datetime.now()}) 159 {"is_vacuate": 1, "update_time": datetime.datetime.now()})
118 sys_session.commit() 160 sys_session.commit()
119 161
120 except Exception as e: 162 except Exception as e:
121 try: 163 try:
122 - sys_session.query(Task).filter_by(guid=task_guid).update({"state": -1,"update_time":datetime.datetime.now()}) 164 + sys_session.query(Task).filter_by(guid=task_guid).update({"state": -1,"update_time":datetime.datetime.now(),
  165 + "process": "精化失败"})
123 sys_session.query(Table).filter_by(guid=table.guid).update( 166 sys_session.query(Table).filter_by(guid=table.guid).update(
124 {"is_vacuate": 0, "update_time": datetime.datetime.now()}) 167 {"is_vacuate": 0, "update_time": datetime.datetime.now()})
125 168
@@ -129,7 +172,8 @@ class Api(ApiTemplate): @@ -129,7 +172,8 @@ class Api(ApiTemplate):
129 task_guid=task_guid) 172 task_guid=task_guid)
130 sys_session.add(task_process) 173 sys_session.add(task_process)
131 sys_session.commit() 174 sys_session.commit()
132 - vacuate_process.rollback() 175 + if vacuate_process:
  176 + vacuate_process.rollback()
133 177
134 print(traceback.format_exc()) 178 print(traceback.format_exc())
135 except Exception as ee: 179 except Exception as ee:
  1 +# author: 4N
  2 +# createtime: 2021/1/27
  3 +# email: nheweijun@sina.com
  4 +
  5 +
  6 +import datetime
  7 +import traceback
  8 +from app.models import Table, Database, DES,Task,db,TableVacuate
  9 +
  10 +from sqlalchemy.engine import ResultProxy
  11 +from app.util.component.ApiTemplate import ApiTemplate
  12 +from app.util.component.PGUtil import PGUtil
  13 +from app.util.component.EntryDataVacuate import Process
  14 +from app.util.component.GeometryAdapter import GeometryAdapter
  15 +from app.util.component.StructuredPrint import StructurePrint
  16 +import multiprocessing
  17 +import uuid
  18 +import configure
  19 +from osgeo.ogr import DataSource,Layer,Geometry
  20 +from osgeo import ogr
  21 +
  22 +class Api(ApiTemplate):
  23 + api_name = "删除抽稀表"
  24 + def process(self):
  25 +
  26 + res = {}
  27 + res["data"] = {}
  28 + pg_ds = None
  29 + try:
  30 + table_guid = self.para.get("guid")
  31 + table: Table = Table.query.filter_by(guid=table_guid).one_or_none()
  32 + grid = None
  33 + if not self.para.get("grid"):
  34 + raise Exception("请输入grids参数!")
  35 + else:
  36 + grid = float(self.para.get("grid"))
  37 +
  38 + if not table:
  39 + raise Exception("数据不存在!")
  40 +
  41 + # 判断图层是否存在
  42 + pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri))
  43 + layer = pg_ds.GetLayerByName(table.name)
  44 +
  45 + # 判断用户权限
  46 + # user, pw, host, port, database = PGUtil.get_info_from_sqlachemy_uri(DES.decode(table.relate_database.sqlalchemy_uri))
  47 + # query_role:Layer = pg_ds.ExecuteSQL("SELECT rolcreatedb FROM pg_roles WHERE rolname='{}'".format(user))
  48 + # if not query_role.GetFeature(0).GetField("rolcreatedb"):
  49 + # raise Exception("用户不具备建表权限!")
  50 +
  51 + if not layer:
  52 + raise Exception("图层不存在!")
  53 +
  54 + #删除数据
  55 + tvs = db.session.query(TableVacuate).filter_by(pixel_distance=grid, table_guid=table.guid).all()
  56 + if not tvs:
  57 + raise Exception("数据不存在!")
  58 + for tv in tvs :
  59 + db.session.delete(tv)
  60 + try:
  61 + pg_ds.DeleteLayer(tv.name)
  62 + except Exception as e :
  63 + StructurePrint.print("抽稀图层不存在!","warn")
  64 + db.session.commit()
  65 + res["result"] = True
  66 +
  67 + except Exception as e:
  68 + raise e
  69 + finally:
  70 + if pg_ds:
  71 + pg_ds.Destroy()
  72 + return res
  73 +
  74 +
  75 + api_doc = {
  76 + "tags": ["管理接口"],
  77 + "parameters": [
  78 + {"name": "guid",
  79 + "in": "formData",
  80 + "type": "string",
  81 + "description": "表guid", "required": "true"},
  82 + {"name": "grid",
  83 + "in": "formData",
  84 + "type": "string",
  85 + "description": "网格大小", "required": "true"}
  86 + ],
  87 + "responses": {
  88 + 200: {
  89 + "schema": {
  90 + "properties": {
  91 + }
  92 + }
  93 + }
  94 + }
  95 + }
  1 +# author: 4N
  2 +# createtime: 2021/1/27
  3 +# email: nheweijun@sina.com
  4 +
  5 +
  6 +from app.models import Table,TableVacuate,Task
  7 +from app.util.component.ApiTemplate import ApiTemplate
  8 +from app.util.component.VacuateConf import VacuateConf
  9 +import collections
  10 +import json
  11 +
  12 +import copy
  13 +class Api(ApiTemplate):
  14 + api_name = "抽稀info"
  15 + def process(self):
  16 +
  17 + res = {}
  18 + try:
  19 +
  20 + lonlat_gridsize = VacuateConf.lonlat_gridsize
  21 + project_gridsize = VacuateConf.project_gridsize
  22 + table_guid = self.para.get("guid")
  23 +
  24 + table: Table = Table.query.filter_by(guid=table_guid).one_or_none()
  25 + if not table:
  26 + raise Exception("数据不存在!")
  27 + tvs = TableVacuate.query.filter_by(table_guid=table_guid).all()
  28 + dat = collections.OrderedDict()
  29 + if float(table.extent.split(",")[0])<180:
  30 + grid_size = copy.copy(lonlat_gridsize)
  31 + else:
  32 + grid_size = copy.copy(project_gridsize)
  33 +
  34 + now_grid = [tv.pixel_distance for tv in tvs]
  35 +
  36 + grid_size.reverse()
  37 +
  38 + # 正在精华的任务
  39 + task_running = Task.query.filter_by(task_type=2,table_guid=table_guid,state=0).all()
  40 + grid_running = []
  41 +
  42 + for t in task_running:
  43 + grid_running.extend(t.parameter.split(","))
  44 +
  45 + for grid in grid_size:
  46 + if grid in now_grid:
  47 + dat[str(grid)] = 1
  48 + else:
  49 + dat[str(grid)] = 0
  50 + if str(grid) in grid_running:
  51 + dat[str(grid)] = 2
  52 +
  53 + res["data"] = json.dumps(dat)
  54 + res["result"] = True
  55 +
  56 + except Exception as e:
  57 + raise e
  58 + return res
  59 +
  60 + api_doc = {
  61 + "tags": ["管理接口"],
  62 + "parameters": [
  63 + {"name": "guid",
  64 + "in": "formData",
  65 + "type": "string",
  66 + "description": "表guid", "required": "true"},
  67 + ],
  68 + "responses": {
  69 + 200: {
  70 + "schema": {
  71 + "properties": {
  72 + }
  73 + }
  74 + }
  75 + }
  76 + }
  1 +# author: 4N
  2 +# createtime: 2021/1/27
  3 +# email: nheweijun@sina.com
  4 +
  5 +
  6 +import datetime
  7 +import traceback
  8 +from app.models import Table, Database, DES,Task,db,TableVacuate
  9 +from app.util.component.ApiTemplate import ApiTemplate
  10 +from app.util.component.PGUtil import PGUtil
  11 +from app.util.component.EntryDataVacuate import Process
  12 +import multiprocessing
  13 +import uuid
  14 +import configure
  15 +from osgeo.ogr import DataSource,Layer,Geometry
  16 +from osgeo import ogr
  17 +from app.util.component.StructuredPrint import StructurePrint
  18 +from app.util.component.VacuateConf import VacuateConf
  19 +
  20 +class Api(ApiTemplate):
  21 + api_name = "单独抽稀"
  22 + def process(self):
  23 +
  24 + res = {}
  25 + res["data"] = {}
  26 + db_session = None
  27 + try:
  28 + table_guid = self.para.get("guid")
  29 + grids = []
  30 + if not self.para.get("grids"):
  31 + raise Exception("请输入grids参数!")
  32 + else:
  33 + grids = [float(x) for x in self.para.get("grids").split(",")]
  34 + grids.sort()
  35 +
  36 + table: Table = Table.query.filter_by(guid=table_guid).one_or_none()
  37 +
  38 + if not table:
  39 + raise Exception("数据不存在!")
  40 +
  41 + # 判断图层是否存在
  42 +
  43 + pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri))
  44 + layer = pg_ds.GetLayerByName(table.name)
  45 +
  46 + # 判断用户权限
  47 + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(table.relate_database.sqlalchemy_uri))
  48 + if not PGUtil.check_table_privilege(table.name,"SELECT",db_tuple[0],pg_ds):
  49 + raise Exception("用户{}对表{}没有select权限!".format(db_tuple[0],table.name))
  50 +
  51 + if not layer:
  52 + raise Exception("图层不存在!")
  53 + if pg_ds:
  54 + pg_ds.Destroy()
  55 +
  56 +
  57 +
  58 + if Task.query.filter_by(table_guid=table_guid,state=0).one_or_none():
  59 + res["result"] = False
  60 + res["msg"] = "数据精化中!"
  61 + return res
  62 + if table.table_type==0:
  63 + res["result"] = False
  64 + res["msg"] = "非空间表!"
  65 + return res
  66 +
  67 + # if table.is_vacuate==1:
  68 + # res["state"] = -1
  69 + # res["message"] = "已精化!"
  70 + # return res
  71 +
  72 + # 初始化task
  73 + task_guid = uuid.uuid1().__str__()
  74 +
  75 + vacuate_process = multiprocessing.Process(target=self.task,args=(table,task_guid,grids))
  76 + vacuate_process.start()
  77 +
  78 +
  79 + task = Task(guid=task_guid,
  80 + name="{}精化,网格大小:{}".format(table.name,self.para.get("grids")),
  81 + table_guid=table_guid,
  82 + create_time=datetime.datetime.now(),
  83 + state=0,
  84 + task_type=2,
  85 + creator=self.para.get("creator"),
  86 + file_name=None,
  87 + database_guid=table.database_guid,
  88 + process="精化中",
  89 + parameter=self.para.get("grids"))
  90 +
  91 + db.session.add(task)
  92 + db.session.commit()
  93 + res["msg"] = "图层抽稀已提交!"
  94 + res["data"] = task_guid
  95 + res["result"] = True
  96 +
  97 + except Exception as e:
  98 + raise e
  99 + finally:
  100 + if db_session:
  101 + db_session.close()
  102 + return res
  103 +
  104 + def task(self,table,task_guid,grids):
  105 +
  106 + sys_session = None
  107 + pg_session = None
  108 + pg_ds = None
  109 + vacuate_process = None
  110 + origin_vacuate = table.is_vacuate
  111 +
  112 + try:
  113 + sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI)
  114 + sys_session.query(Table).filter_by(guid=table.guid).update(
  115 + {"is_vacuate": 2, "update_time": datetime.datetime.now()})
  116 + sys_session.commit()
  117 +
  118 +
  119 + database = sys_session.query(Database).filter_by(guid=table.database_guid).one_or_none()
  120 + pg_session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri))
  121 +
  122 + pg_ds :DataSource= PGUtil.open_pg_data_source(1,DES.decode(database.sqlalchemy_uri))
  123 +
  124 + # 创建抽稀过程
  125 + options = ["OVERWRITE=yes", "GEOMETRY_NAME={}".format(PGUtil.get_geo_column(table.name,pg_session)),
  126 + "PRECISION=NO"]
  127 +
  128 + layer = pg_ds.GetLayerByName(table.name)
  129 +
  130 + vacuate_process:VacuateProcess = VacuateProcess(layer, table.name, options,database.sqlalchemy_uri,grids)
  131 +
  132 +
  133 + for feature in layer:
  134 + geo = feature.GetGeometryRef()
  135 + #插入抽稀图层
  136 + if geo is not None:
  137 + vacuate_process.vacuate(geo)
  138 +
  139 + #删除原有数据
  140 + for grid in grids:
  141 + tvs = sys_session.query(TableVacuate).filter_by(pixel_distance=grid,table_guid=table.guid).all()
  142 + for tv in tvs :
  143 + sys_session.delete(tv)
  144 +
  145 +
  146 + #新增
  147 + for l in range(vacuate_process.max_level):
  148 + layer_name = vacuate_process.vacuate_layers[l].GetName()
  149 + lev = layer_name.split("_")[-2]
  150 +
  151 + table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(),
  152 + table_guid=table.guid,
  153 + level=int(lev),
  154 + name=layer_name,
  155 + pixel_distance=vacuate_process.this_gridsize[l])
  156 + sys_session.add(table_vacuate)
  157 +
  158 + sys_session.query(Task).filter_by(guid=task_guid).update({"state":1,"update_time":datetime.datetime.now(),
  159 + "process" : "精化完成"})
  160 + sys_session.query(Table).filter_by(guid=table.guid).update(
  161 + {"is_vacuate": 1, "update_time": datetime.datetime.now()})
  162 + sys_session.commit()
  163 +
  164 + except Exception as e:
  165 + try:
  166 + sys_session.query(Task).filter_by(guid=task_guid).update({"state": -1,"update_time":datetime.datetime.now(),
  167 + "process": "精化失败"})
  168 + sys_session.query(Table).filter_by(guid=table.guid).update(
  169 + {"is_vacuate": origin_vacuate, "update_time": datetime.datetime.now()})
  170 +
  171 + message = "{} {}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), e.__str__())
  172 + task_process_guid = uuid.uuid1().__str__()
  173 + task_process = Process(guid=task_process_guid, message=message, time=datetime.datetime.now(),
  174 + task_guid=task_guid)
  175 + sys_session.add(task_process)
  176 + sys_session.commit()
  177 + if vacuate_process:
  178 + vacuate_process.rollback()
  179 +
  180 + print(traceback.format_exc())
  181 + except Exception as ee:
  182 + print(traceback.format_exc())
  183 + finally:
  184 + try:
  185 + if vacuate_process:
  186 + vacuate_process.end()
  187 + if sys_session:
  188 + sys_session.close()
  189 + if pg_session:
  190 + pg_session.close()
  191 + if pg_ds:
  192 + pg_ds.Destroy()
  193 + except:
  194 + print(traceback.format_exc())
  195 +
  196 + api_doc = {
  197 + "tags": ["管理接口"],
  198 + "parameters": [
  199 + {"name": "guid",
  200 + "in": "formData",
  201 + "type": "string",
  202 + "description": "表guid", "required": "true"},
  203 + {"name": "grids",
  204 + "in": "formData",
  205 + "type": "string",
  206 + "description": "需要抽稀的网格大小,以逗号相隔", "required": "true"}
  207 + ],
  208 + "responses": {
  209 + 200: {
  210 + "schema": {
  211 + "properties": {
  212 + }
  213 + }
  214 + }
  215 + }
  216 + }
  217 +
  218 +
  219 +class VacuateProcess:
  220 + '''
  221 + 抽稀类
  222 + '''
  223 +
  224 + max_level=0
  225 + fill_dict={}
  226 + vacuate_layers={}
  227 + vacuate_layers_gridsize={}
  228 + pg_ds_dict = {}
  229 + #被抽吸图层的范围
  230 + extent=[]
  231 + is_spatial=False
  232 + #该抽稀过程的抽稀网格
  233 + this_gridsize=[]
  234 +
  235 +
  236 + def __init__(self,layer:Layer,new_layer_name, options,sqlalchemy_uri,grids):
  237 +
  238 + #是空间图层才初始化
  239 + if layer.GetExtent()[0] > 0 or layer.GetExtent()[0] < 0:
  240 +
  241 + self.is_spatial=True
  242 +
  243 + # 判断需要抽稀多少级
  244 +
  245 + extent = layer.GetExtent()
  246 + self.extent=extent
  247 +
  248 + layer.SetSpatialFilter(None)
  249 + layer.ResetReading()
  250 +
  251 + self.this_gridsize = grids
  252 + self.max_level = len(grids)
  253 +
  254 +
  255 + # 创建抽稀ds
  256 + for l in range(self.max_level):
  257 + pg_ds_l: DataSource = PGUtil.open_pg_data_source(1, DES.decode(sqlalchemy_uri))
  258 + pg_ds_l.StartTransaction()
  259 + self.pg_ds_dict[l] = pg_ds_l
  260 +
  261 + # 生成抽稀图层
  262 + options = options[1:]
  263 + options.append("OVERWRITE=yes")
  264 + options.append("LAUNDER=no")
  265 + for l in range(self.max_level):
  266 + this_grid_len = self.this_gridsize[l]
  267 +
  268 + self.vacuate_layers_gridsize[l] = this_grid_len
  269 +
  270 + pg = self.pg_ds_dict[l]
  271 +
  272 + if this_grid_len<1:
  273 + grid_name = str(this_grid_len).split(".")[-1]
  274 + if this_grid_len.__eq__(0.000075):
  275 + grid_name = "000075"
  276 + else:
  277 + grid_name = str(int(this_grid_len))
  278 +
  279 + # 抽稀图层是点面混合的
  280 + # 抽稀表有固定的命名规则
  281 + # 抽稀表一定要覆盖
  282 +
  283 + this_grid_szie = VacuateConf.project_gridsize if VacuateConf.project_gridsize.__contains__(this_grid_len) else VacuateConf.lonlat_gridsize
  284 +
  285 + lev = this_grid_szie.index(this_grid_len)
  286 + print("{}:{}".format(grid_name, lev))
  287 + vl = pg.CreateLayer("{}_vacuate_{}_{}".format(new_layer_name, lev, grid_name), layer.GetSpatialRef(),
  288 + ogr.wkbUnknown, options)
  289 + # 抽稀表不需要属性
  290 + # vl.CreateFields(schema)
  291 + self.vacuate_layers[l] = vl
  292 +
  293 + else:
  294 + pass
  295 +
  296 +
  297 + def vacuate(self,g):
  298 +
  299 + if self.is_spatial:
  300 +
  301 + # 插入到所有抽稀图层中
  302 + for level in range(self.max_level):
  303 +
  304 + center: Geometry = g.Centroid()
  305 +
  306 + extent = g.GetEnvelope()
  307 + long_extent= extent[1]-extent[0]
  308 + lat_extent = extent[3]-extent[2]
  309 +
  310 + this_grid_len =self.vacuate_layers_gridsize[level]
  311 +
  312 + row = int((center.GetY() - self.extent[2]) / this_grid_len)
  313 + col = int((center.GetX() - self.extent[0]) / this_grid_len)
  314 + key = "{}.{}.{}".format(level, row, col)
  315 +
  316 + if not self.fill_dict.get(key):
  317 + self.fill_dict[key] = 0
  318 + if self.fill_dict[key] == 0:
  319 +
  320 + vacuate_layer: Layer = self.vacuate_layers.get(level)
  321 + feat = ogr.Feature(vacuate_layer.GetLayerDefn())
  322 + # 如果图形比网格小,直接存储其中心点
  323 + if this_grid_len>long_extent and this_grid_len>lat_extent:
  324 + feat.SetGeometry(center)
  325 + else:
  326 + feat.SetGeometry(g)
  327 + vacuate_layer.CreateFeature(feat)
  328 + self.fill_dict[key] += 1
  329 +
  330 + def end(self):
  331 + for pg in self.pg_ds_dict.values():
  332 + pg.Destroy()
  333 +
  334 + def rollback(self):
  335 + for pg in self.pg_ds_dict.values():
  336 + pg.RollbackTransaction()
  1 +# author: 4N
  2 +# createtime: 2021/1/27
  3 +# email: nheweijun@sina.com
  4 +
  5 +
  6 +import datetime
  7 +import traceback
  8 +from app.models import Table, Database, DES,Task,db,TableVacuate
  9 +
  10 +from sqlalchemy.engine import ResultProxy
  11 +from app.util.component.ApiTemplate import ApiTemplate
  12 +from app.util.component.PGUtil import PGUtil
  13 +from app.util.component.EntryDataVacuate import Process
  14 +from app.util.component.GeometryAdapter import GeometryAdapter
  15 +from app.util.component.StructuredPrint import StructurePrint
  16 +import multiprocessing
  17 +import uuid
  18 +import configure
  19 +from osgeo.ogr import DataSource,Layer,Geometry
  20 +from osgeo import ogr
  21 +from app.util.component.VacuateConf import VacuateConf
  22 +import copy
  23 +class Api(ApiTemplate):
  24 + api_name = "推荐抽稀"
  25 + def process(self):
  26 +
  27 + res = {}
  28 + res["data"] = {}
  29 + pg_ds = None
  30 + try:
  31 + table_guid = self.para.get("guid")
  32 +
  33 +
  34 + table: Table = Table.query.filter_by(guid=table_guid).one_or_none()
  35 +
  36 +
  37 + if not table:
  38 + raise Exception("数据不存在!")
  39 +
  40 + # 判断图层是否存在
  41 +
  42 + pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri))
  43 + layer = pg_ds.GetLayerByName(table.name)
  44 +
  45 + # 判断用户权限
  46 + user, pw, host, port, database = PGUtil.get_info_from_sqlachemy_uri(DES.decode(table.relate_database.sqlalchemy_uri))
  47 + query_role:Layer = pg_ds.ExecuteSQL("SELECT rolcreatedb FROM pg_roles WHERE rolname='{}'".format(user))
  48 + if not query_role.GetFeature(0).GetField("rolcreatedb"):
  49 + raise Exception("用户不具备建表权限!")
  50 +
  51 + if not layer:
  52 + raise Exception("图层不存在!")
  53 +
  54 +
  55 + lonlat_gridsize = copy.deepcopy(VacuateConf.lonlat_gridsize)
  56 + project_gridsize = copy.deepcopy(VacuateConf.project_gridsize)
  57 + least_vacuate_count = copy.deepcopy(VacuateConf.least_vacuate_count)
  58 +
  59 + this_gridsize = []
  60 + max_level = 0
  61 + # 是空间图层才初始化
  62 + if layer.GetExtent()[0] > 0 or layer.GetExtent()[0] < 0:
  63 +
  64 +
  65 + # 判断需要抽稀多少级
  66 + lc = layer.GetFeatureCount()
  67 + extent = layer.GetExtent()
  68 +
  69 + # 判断疏密程度
  70 + p_x = (extent[1] - extent[0]) / 10.0
  71 + p_y = (extent[3] - extent[2]) / 10.0
  72 + fill_precent = 0
  73 + StructurePrint.print("判断疏密")
  74 + for ix in range(10):
  75 + for iy in range(10):
  76 + grid_extent = [extent[0] + ix * p_x, extent[0] + ix * p_x + p_x, extent[2] + iy * p_y,
  77 + extent[2] + iy * p_y + p_y]
  78 + poly = GeometryAdapter.envelop_2_polygon(grid_extent)
  79 +
  80 + layer.SetSpatialFilter(None)
  81 + layer.SetSpatialFilter(poly)
  82 + layer.ResetReading()
  83 + if layer.GetNextFeature():
  84 + fill_precent += 1
  85 +
  86 + print(fill_precent)
  87 + StructurePrint.print("判断疏密结束")
  88 +
  89 + layer.SetSpatialFilter(None)
  90 + layer.ResetReading()
  91 + # 固有疏密程度
  92 + original_density = 8
  93 +
  94 + if extent[0] > 180:
  95 + t_grid_size = project_gridsize
  96 + else:
  97 + t_grid_size = lonlat_gridsize
  98 + for grid_size in t_grid_size:
  99 + # 最少抽稀个数
  100 + if lc > least_vacuate_count:
  101 + # 网格数至少大于
  102 + if ((extent[1] - extent[0]) * (extent[3] - extent[2])) / (
  103 + grid_size ** 2) > least_vacuate_count:
  104 + # 要素数量大于网格数量
  105 + # 要考虑图层的疏密程度,original_density*(100.0/fill_precent) 为疏密指数
  106 + if lc * original_density * (100.0 / fill_precent) > (
  107 + (extent[1] - extent[0]) * (extent[3] - extent[2])) / (grid_size ** 2):
  108 + this_gridsize.append(grid_size)
  109 + max_level += 1
  110 +
  111 + res["data"] = this_gridsize
  112 + res["result"] = True
  113 +
  114 +
  115 + except Exception as e:
  116 + raise e
  117 + finally:
  118 + if pg_ds:
  119 + pg_ds.Destroy()
  120 + return res
  121 +
  122 +
  123 + api_doc = {
  124 + "tags": ["管理接口"],
  125 + "parameters": [
  126 + {"name": "guid",
  127 + "in": "formData",
  128 + "type": "string",
  129 + "description": "表guid", "required": "true"}
  130 + ],
  131 + "responses": {
  132 + 200: {
  133 + "schema": {
  134 + "properties": {
  135 + }
  136 + }
  137 + }
  138 + }
  139 + }
@@ -16,6 +16,7 @@ from functools import lru_cache @@ -16,6 +16,7 @@ from functools import lru_cache
16 import traceback 16 import traceback
17 import copy 17 import copy
18 from app.util.component.GeometryAdapter import GeometryAdapter 18 from app.util.component.GeometryAdapter import GeometryAdapter
  19 +from app.util.component.VacuateConf import VacuateConf
19 class EntryDataVacuate: 20 class EntryDataVacuate:
20 21
21 def entry(self,parameter): 22 def entry(self,parameter):
@@ -317,13 +318,15 @@ class ThisTask: @@ -317,13 +318,15 @@ class ThisTask:
317 else: 318 else:
318 ext = [round(e, 2) for e in ext] 319 ext = [round(e, 2) for e in ext]
319 320
  321 + geom_type = GeometryAdapter.get_geometry_type(layer)
  322 +
320 extent = "{},{},{},{}".format(ext[0], ext[1], ext[2], ext[3]) 323 extent = "{},{},{},{}".format(ext[0], ext[1], ext[2], ext[3])
321 table_guid = uuid.uuid1().__str__() 324 table_guid = uuid.uuid1().__str__()
322 table = Table(guid=table_guid, 325 table = Table(guid=table_guid,
323 database_guid=self.database.guid, 326 database_guid=self.database.guid,
324 creator=creator, 327 creator=creator,
325 name=new_layer_name, create_time=this_time, update_time=this_time, 328 name=new_layer_name, create_time=this_time, update_time=this_time,
326 - catalog_guid=self.catalog_guid, table_type=GeometryAdapter.get_table_type(GeometryAdapter.get_geometry_type(layer)), 329 + catalog_guid=self.catalog_guid, table_type=GeometryAdapter.get_table_type(geom_type),
327 extent=extent, 330 extent=extent,
328 feature_count=layer.GetFeatureCount(), 331 feature_count=layer.GetFeatureCount(),
329 is_vacuate=is_vacuate 332 is_vacuate=is_vacuate
@@ -353,13 +356,16 @@ class ThisTask: @@ -353,13 +356,16 @@ class ThisTask:
353 # 抽稀表有固定的命名规则 356 # 抽稀表有固定的命名规则
354 for level,layer in vacuate_layers.items(): 357 for level,layer in vacuate_layers.items():
355 pixel_distance_str:str=layer.GetName().split("_")[-1] 358 pixel_distance_str:str=layer.GetName().split("_")[-1]
  359 + lev = layer.GetName().split("_")[-2]
  360 +
356 if pixel_distance_str.startswith("0"): 361 if pixel_distance_str.startswith("0"):
357 pixel_distance_str="0.{}".format(pixel_distance_str) 362 pixel_distance_str="0.{}".format(pixel_distance_str)
358 363
359 pixel_distance = float(pixel_distance_str) 364 pixel_distance = float(pixel_distance_str)
  365 +
360 table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(), 366 table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(),
361 table_guid=table_guid, 367 table_guid=table_guid,
362 - level=level, 368 + level=int(lev),
363 name=layer.GetName(), 369 name=layer.GetName(),
364 pixel_distance=pixel_distance) 370 pixel_distance=pixel_distance)
365 self.sys_session.add(table_vacuate) 371 self.sys_session.add(table_vacuate)
@@ -398,14 +404,18 @@ class VacuateProcess: @@ -398,14 +404,18 @@ class VacuateProcess:
398 vacuate_layers_gridsize={} 404 vacuate_layers_gridsize={}
399 pg_ds_dict = {} 405 pg_ds_dict = {}
400 # 图层要素大于5W才抽稀 406 # 图层要素大于5W才抽稀
401 - least_vacuate_count = 20000 407 + least_vacuate_count = VacuateConf.least_vacuate_count
402 408
403 extent=[] 409 extent=[]
404 is_spatial=False 410 is_spatial=False
405 - # 网格大小是固定的,根据图层的信息滑动选取需要抽稀的等级  
406 - lonlat_gridsize=[0.000075,0.00015,0.0003,0.0006,0.0012,0.0024,0.0048,0.0096,0.0192,0.0384,0.0768]  
407 - project_gridsize=[15,30,60,120,240,480,960,1920,3840,7680]  
408 411
  412 + lonlat_gridsize = VacuateConf.lonlat_gridsize
  413 + project_gridsize = VacuateConf.project_gridsize
  414 +
  415 + # 该抽稀过程使用的grid_size
  416 + t_grid_size = []
  417 +
  418 + # 该抽稀过程的抽稀网格
409 this_gridsize=[] 419 this_gridsize=[]
410 420
411 421
@@ -453,17 +463,17 @@ class VacuateProcess: @@ -453,17 +463,17 @@ class VacuateProcess:
453 ###### 463 ######
454 464
455 if extent[0]>180: 465 if extent[0]>180:
456 - t_grid_size=self.project_gridsize 466 + self.t_grid_size=self.project_gridsize
457 else: 467 else:
458 - t_grid_size = self.lonlat_gridsize  
459 - for grid_size in t_grid_size: 468 + self.t_grid_size = self.lonlat_gridsize
  469 + for grid_size in self.t_grid_size:
460 # 最少抽稀个数 470 # 最少抽稀个数
461 - if lc>self.least_vacuate_count: 471 + if lc > self.least_vacuate_count:
462 # 网格数至少大于 472 # 网格数至少大于
463 - if ((extent[1] - extent[0])*(extent[3] - extent[2]))/(grid_size**2)>self.least_vacuate_count: 473 + if ((extent[1] - extent[0]) * (extent[3] - extent[2])) / (grid_size**2)>self.least_vacuate_count:
464 # 要素数量大于网格数量 474 # 要素数量大于网格数量
465 # 要考虑图层的疏密程度,original_density*(100.0/fill_precent) 为疏密指数 475 # 要考虑图层的疏密程度,original_density*(100.0/fill_precent) 为疏密指数
466 - if lc*original_density*(100.0/fill_precent)>((extent[1] - extent[0])*(extent[3] - extent[2]))/(grid_size**2) : 476 + if lc * original_density * (100.0/fill_precent)>((extent[1] - extent[0])*(extent[3] - extent[2]))/(grid_size**2) :
467 print(grid_size) 477 print(grid_size)
468 self.this_gridsize.append(grid_size) 478 self.this_gridsize.append(grid_size)
469 self.max_level += 1 479 self.max_level += 1
@@ -479,6 +489,7 @@ class VacuateProcess: @@ -479,6 +489,7 @@ class VacuateProcess:
479 # 生成抽稀图层 489 # 生成抽稀图层
480 options = options[1:] 490 options = options[1:]
481 options.append("OVERWRITE=yes") 491 options.append("OVERWRITE=yes")
  492 + options.append("LAUNDER=no")
482 for l in range(self.max_level): 493 for l in range(self.max_level):
483 this_grid_len = self.this_gridsize[l] 494 this_grid_len = self.this_gridsize[l]
484 495
@@ -496,7 +507,8 @@ class VacuateProcess: @@ -496,7 +507,8 @@ class VacuateProcess:
496 # 抽稀表有固定的命名规则 507 # 抽稀表有固定的命名规则
497 # 抽稀表一定要覆盖 508 # 抽稀表一定要覆盖
498 509
499 - vl = pg.CreateLayer("{}_vacuate_{}_{}".format(new_layer_name, l, grid_name), layer.GetSpatialRef(), 510 +
  511 + vl = pg.CreateLayer("{}_vacuate_{}_{}".format(new_layer_name, self.t_grid_size.index(this_grid_len), grid_name), layer.GetSpatialRef(),
500 ogr.wkbUnknown, options) 512 ogr.wkbUnknown, options)
501 # 抽稀表不需要属性 513 # 抽稀表不需要属性
502 # vl.CreateFields(schema) 514 # vl.CreateFields(schema)
@@ -5,8 +5,6 @@ @@ -5,8 +5,6 @@
5 from osgeo import ogr 5 from osgeo import ogr
6 from sqlalchemy import create_engine 6 from sqlalchemy import create_engine
7 from sqlalchemy.orm import sessionmaker,Session 7 from sqlalchemy.orm import sessionmaker,Session
8 -from sqlalchemy.engine import ResultProxy  
9 -  
10 class PGUtil: 8 class PGUtil:
11 9
12 @classmethod 10 @classmethod
@@ -27,11 +25,6 @@ class PGUtil: @@ -27,11 +25,6 @@ class PGUtil:
27 25
28 @classmethod 26 @classmethod
29 def get_info_from_sqlachemy_uri(cls,uri): 27 def get_info_from_sqlachemy_uri(cls,uri):
30 - '''  
31 - 解析sqlachemy_uri  
32 - :param uri:  
33 - :return:  
34 - '''  
35 parts = uri.split(":") 28 parts = uri.split(":")
36 user = parts[1][2:] 29 user = parts[1][2:]
37 30
@@ -56,12 +49,7 @@ class PGUtil: @@ -56,12 +49,7 @@ class PGUtil:
56 49
57 @classmethod 50 @classmethod
58 def get_geo_column(cls,table_name,db_session): 51 def get_geo_column(cls,table_name,db_session):
59 - '''  
60 # 判断空间列 52 # 判断空间列
61 - :param table_name:  
62 - :param db_session:  
63 - :return:  
64 - '''  
65 geom_col_sql = ''' 53 geom_col_sql = '''
66 SELECT a.attname AS field,t.typname AS type 54 SELECT a.attname AS field,t.typname AS type
67 FROM 55 FROM
@@ -75,7 +63,7 @@ class PGUtil: @@ -75,7 +63,7 @@ class PGUtil:
75 and a.atttypid = t.oid 63 and a.atttypid = t.oid
76 '''.format(table_name) 64 '''.format(table_name)
77 geom_col = None 65 geom_col = None
78 - geom_result: ResultProxy = db_session.execute(geom_col_sql) 66 + geom_result = db_session.execute(geom_col_sql)
79 for row_proxy in geom_result: 67 for row_proxy in geom_result:
80 if row_proxy[1].__eq__("geometry"): 68 if row_proxy[1].__eq__("geometry"):
81 geom_col = row_proxy[0] 69 geom_col = row_proxy[0]
@@ -84,39 +72,39 @@ class PGUtil: @@ -84,39 +72,39 @@ class PGUtil:
84 72
85 @classmethod 73 @classmethod
86 def get_table_count(cls,table_name,db_session): 74 def get_table_count(cls,table_name,db_session):
87 - '''  
88 - 获取图层数量  
89 - :param table_name:  
90 - :param db_session:  
91 - :return:  
92 - '''  
93 count_result = db_session.execute('''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format( 75 count_result = db_session.execute('''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(
94 table_name)).fetchone() 76 table_name)).fetchone()
95 count = count_result[0] 77 count = count_result[0]
96 if count< 1000000: 78 if count< 1000000:
97 - count_result: ResultProxy = db_session.execute('select count(*) from "{}"'.format(table_name)).fetchone() 79 + count_result = db_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()
98 count=count_result[0] 80 count=count_result[0]
99 return count 81 return count
100 82
101 @classmethod 83 @classmethod
102 - def check_space(cls, sqlachemy_uri): 84 + def check_table_privilege(cls,table_name,pri_type,user,pg_ds):
103 ''' 85 '''
104 - 判断数据库是否为空间库  
105 - :param sqlachemy_uri: 86 + 通过pg_ds来判断用户是否对表具有权限
  87 + :param table_name:
  88 + :param pri_type:
  89 + :param user:
  90 + :param pg_ds:
106 :return: 91 :return:
107 ''' 92 '''
108 - system_session = None  
109 - check = True  
110 - try:  
111 - test_sql = "select st_geometryfromtext('POINT(1 1)')"  
112 - engine = create_engine(sqlachemy_uri)  
113 - system_session = sessionmaker(bind=engine)()  
114 - system_session.execute(test_sql).fetchone()  
115 - except:  
116 - check = False  
117 - finally:  
118 - if system_session:  
119 - system_session.close()  
120 -  
121 - return check  
122 93
  94 + pri = pg_ds.ExecuteSQL("select * from information_schema.table_privileges "
  95 + "where grantee='{}' and table_name='{}' and privilege_type='{}' "
  96 + .format(user,table_name,pri_type))
  97 +
  98 + if pri.GetNextFeature():
  99 + return True
  100 + else:
  101 + return False
  102 +
  103 +
  104 + @classmethod
  105 + def check_database_privilege(cls,table_name,pri_type,user,session):
  106 + pass
  107 +
  108 + @classmethod
  109 + def check_database_privilege(cls,table_name,pri_type,user,session):
  110 + pass
@@ -8,11 +8,45 @@ class SQLUtil: @@ -8,11 +8,45 @@ class SQLUtil:
8 8
9 9
10 @classmethod 10 @classmethod
11 - def get_count(cls,session,table_name):  
12 - count = session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0] 11 + def get_table_count(cls,table_name,db_session):
  12 + count_result = db_session.execute('''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(
  13 + table_name)).fetchone()
  14 + count = count_result[0]
  15 + if count< 1000000:
  16 + count_result = db_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()
  17 + count=count_result[0]
13 return count 18 return count
14 19
15 @classmethod 20 @classmethod
16 def rename(cls,session,origin,after_name): 21 def rename(cls,session,origin,after_name):
17 rename_sql = 'alter table "{}" rename to "{}"'.format(origin, after_name) 22 rename_sql = 'alter table "{}" rename to "{}"'.format(origin, after_name)
18 session.execute(rename_sql) 23 session.execute(rename_sql)
  24 + session.commit()
  25 +
  26 + @classmethod
  27 + def check_table_privilege(cls,table_name,pri_type,user,session):
  28 + '''
  29 + 判断用户是否对表具有权限
  30 + :param table_name:
  31 + :param pri_type:
  32 + :param user:
  33 + :param pg_ds:
  34 + :return:
  35 + '''
  36 + pri = session.execute("select * from information_schema.table_privileges "
  37 + "where grantee='{}' and table_name='{}' and privilege_type='{}' "
  38 + .format(user,table_name,pri_type)).fetchall()
  39 + if len(pri) == 1:
  40 + return True
  41 + else:
  42 + return False
  43 +
  44 +
  45 +
  46 + @classmethod
  47 + def check_database_privilege(cls,table_name,pri_type,user,session):
  48 + pass
  49 +
  50 + @classmethod
  51 + def check_database_privilege_pg(cls,table_name,pri_type,user,session):
  52 + pass
  1 +# coding=utf-8
  2 +#author: 4N
  3 +#createtime: 2021/8/25
  4 +#email: nheweijun@sina.com
  5 +
  6 +
  7 +class VacuateConf:
  8 + least_vacuate_count = 20000
  9 + lonlat_gridsize = [0.00008, 0.00016, 0.00032, 0.00064, 0.00128, 0.00256, 0.00512, 0.01024, 0.02048,0.04096, 0.08192]
  10 + project_gridsize = [8,16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]
1 -LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py39.cpython-39-x86_64-linux-gnu.so"  
2 - "/usr"  
3 -  
4 - conf.d/*.conf  
5 -<VirtualHost *>  
6 - ServerName dampmanager  
7 - WSGIDaemonProcess yourapplication user=chinadci group=chinadci threads=5  
8 - WSGIScriptAlias /DMapManager /usr/src/DMapManager/run.wsgi  
9 - <Directory /usr/src/>  
10 - WSGIProcessGroup yourapplication  
11 - WSGIApplicationGroup %{GLOBAL}  
12 - Require all granted  
13 - </Directory>  
14 -</VirtualHost>  
15 -  
16 -<virtualhost *:80>  
17 - ServerName dampmanager  
18 - WSGIDaemonProcess mlfans threads=5  
19 - WSGIScriptAlias / /var/www/mlfans/app.wsgi  
20 -  
21 - <directory /var/www/mlfans>  
22 - WSGIProcessGroup mlfans  
23 - WSGIApplicationGroup %{GLOBAL}  
24 - WSGIScriptReloading On  
25 - Order deny,allow  
26 - Allow from all  
27 - </directory>  
28 -</virtualhost>  
29 -  
30 -  
31 -  
32 -  
33 -LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py39.cpython-39-x86_64-linux-gnu.so"  
34 -WSGIPythonHome "/usr"  
35 -  
36 -WSGIScriptAlias /DMapManager /usr/DMapManager/run.wsgi  
37 -<Directory /usr/>  
38 - Require all granted  
39 -</Directory>  
  1 +#
  2 +# This is the main Apache HTTP server configuration file. It contains the
  3 +# configuration directives that give the server its instructions.
  4 +# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
  5 +# In particular, see
  6 +# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
  7 +# for a discussion of each configuration directive.
  8 +#
  9 +# Do NOT simply read the instructions in here without understanding
  10 +# what they do. They're here only as hints or reminders. If you are unsure
  11 +# consult the online docs. You have been warned.
  12 +#
  13 +# Configuration and logfile names: If the filenames you specify for many
  14 +# of the server's control files begin with "/" (or "drive:/" for Win32), the
  15 +# server will use that explicit path. If the filenames do *not* begin
  16 +# with "/", the value of ServerRoot is prepended -- so 'log/access_log'
  17 +# with ServerRoot set to '/www' will be interpreted by the
  18 +# server as '/www/log/access_log', where as '/log/access_log' will be
  19 +# interpreted as '/log/access_log'.
  20 +
  21 +#
  22 +# ServerRoot: The top of the directory tree under which the server's
  23 +# configuration, error, and log files are kept.
  24 +#
  25 +# Do not add a slash at the end of the directory path. If you point
  26 +# ServerRoot at a non-local disk, be sure to specify a local disk on the
  27 +# Mutex directive, if file-based mutexes are used. If you wish to share the
  28 +# same ServerRoot for multiple httpd daemons, you will need to change at
  29 +# least PidFile.
  30 +#
  31 +ServerRoot "/etc/httpd"
  32 +
  33 +#
  34 +# Listen: Allows you to bind Apache to specific IP addresses and/or
  35 +# ports, instead of the default. See also the <VirtualHost>
  36 +# directive.
  37 +#
  38 +# Change this to Listen on specific IP addresses as shown below to
  39 +# prevent Apache from glomming onto all bound IP addresses.
  40 +#
  41 +#Listen 12.34.56.78:80
  42 +Listen 80
  43 +
  44 +#
  45 +# Dynamic Shared Object (DSO) Support
  46 +#
  47 +# To be able to use the functionality of a module which was built as a DSO you
  48 +# have to place corresponding `LoadModule' lines at this location so the
  49 +# directives contained in it are actually available _before_ they are used.
  50 +# Statically compiled modules (those listed by `httpd -l') do not need
  51 +# to be loaded here.
  52 +#
  53 +# Example:
  54 +# LoadModule foo_module modules/mod_foo.so
  55 +#
  56 +Include conf.modules.d/*.conf
  57 +
  58 +#
  59 +# If you wish httpd to run as a different user or group, you must run
  60 +# httpd as root initially and it will switch.
  61 +#
  62 +# User/Group: The name (or #number) of the user/group to run httpd as.
  63 +# It is usually good practice to create a dedicated user and group for
  64 +# running httpd, as with most system services.
  65 +#
  66 +User apache
  67 +Group apache
  68 +
  69 +# 'Main' server configuration
  70 +#
  71 +# The directives in this section set up the values used by the 'main'
  72 +# server, which responds to any requests that aren't handled by a
  73 +# <VirtualHost> definition. These values also provide defaults for
  74 +# any <VirtualHost> containers you may define later in the file.
  75 +#
  76 +# All of these directives may appear inside <VirtualHost> containers,
  77 +# in which case these default settings will be overridden for the
  78 +# virtual host being defined.
  79 +#
  80 +
  81 +#
  82 +# ServerAdmin: Your address, where problems with the server should be
  83 +# e-mailed. This address appears on some server-generated pages, such
  84 +# as error documents. e.g. admin@your-domain.com
  85 +#
  86 +ServerAdmin root@localhost
  87 +
  88 +#
  89 +# ServerName gives the name and port that the server uses to identify itself.
  90 +# This can often be determined automatically, but we recommend you specify
  91 +# it explicitly to prevent problems during startup.
  92 +#
  93 +# If your host doesn't have a registered DNS name, enter its IP address here.
  94 +#
  95 +#ServerName www.example.com:80
  96 +
  97 +#
  98 +# Deny access to the entirety of your server's filesystem. You must
  99 +# explicitly permit access to web content directories in other
  100 +# <Directory> blocks below.
  101 +#
  102 +<Directory />
  103 + AllowOverride none
  104 + Require all denied
  105 +</Directory>
  106 +
  107 +#
  108 +# Note that from this point forward you must specifically allow
  109 +# particular features to be enabled - so if something's not working as
  110 +# you might expect, make sure that you have specifically enabled it
  111 +# below.
  112 +#
  113 +
  114 +#
  115 +# DocumentRoot: The directory out of which you will serve your
  116 +# documents. By default, all requests are taken from this directory, but
  117 +# symbolic links and aliases may be used to point to other locations.
  118 +#
  119 +DocumentRoot "/var/www/html"
  120 +
  121 +#
  122 +# Relax access to content within /var/www.
  123 +#
  124 +<Directory "/var/www">
  125 + AllowOverride None
  126 + # Allow open access:
  127 + Require all granted
  128 +</Directory>
  129 +
  130 +# Further relax access to the default document root:
  131 +<Directory "/var/www/html">
  132 + #
  133 + # Possible values for the Options directive are "None", "All",
  134 + # or any combination of:
  135 + # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
  136 + #
  137 + # Note that "MultiViews" must be named *explicitly* --- "Options All"
  138 + # doesn't give it to you.
  139 + #
  140 + # The Options directive is both complicated and important. Please see
  141 + # http://httpd.apache.org/docs/2.4/mod/core.html#options
  142 + # for more information.
  143 + #
  144 + Options Indexes FollowSymLinks
  145 +
  146 + #
  147 + # AllowOverride controls what directives may be placed in .htaccess files.
  148 + # It can be "All", "None", or any combination of the keywords:
  149 + # Options FileInfo AuthConfig Limit
  150 + #
  151 + AllowOverride None
  152 +
  153 + #
  154 + # Controls who can get stuff from this server.
  155 + #
  156 + Require all granted
  157 +</Directory>
  158 +
  159 +#
  160 +# DirectoryIndex: sets the file that Apache will serve if a directory
  161 +# is requested.
  162 +#
  163 +<IfModule dir_module>
  164 + DirectoryIndex index.html
  165 +</IfModule>
  166 +
  167 +#
  168 +# The following lines prevent .htaccess and .htpasswd files from being
  169 +# viewed by Web clients.
  170 +#
  171 +<Files ".ht*">
  172 + Require all denied
  173 +</Files>
  174 +
  175 +#
  176 +# ErrorLog: The location of the error log file.
  177 +# If you do not specify an ErrorLog directive within a <VirtualHost>
  178 +# container, error messages relating to that virtual host will be
  179 +# logged here. If you *do* define an error logfile for a <VirtualHost>
  180 +# container, that host's errors will be logged there and not here.
  181 +#
  182 +ErrorLog "logs/error_log"
  183 +
  184 +#
  185 +# LogLevel: Control the number of messages logged to the error_log.
  186 +# Possible values include: debug, info, notice, warn, error, crit,
  187 +# alert, emerg.
  188 +#
  189 +LogLevel warn
  190 +
  191 +<IfModule log_config_module>
  192 + #
  193 + # The following directives define some format nicknames for use with
  194 + # a CustomLog directive (see below).
  195 + #
  196 + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
  197 + LogFormat "%h %l %u %t \"%r\" %>s %b" common
  198 +
  199 + <IfModule logio_module>
  200 + # You need to enable mod_logio.c to use %I and %O
  201 + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
  202 + </IfModule>
  203 +
  204 + #
  205 + # The location and format of the access logfile (Common Logfile Format).
  206 + # If you do not define any access logfiles within a <VirtualHost>
  207 + # container, they will be logged here. Contrariwise, if you *do*
  208 + # define per-<VirtualHost> access logfiles, transactions will be
  209 + # logged therein and *not* in this file.
  210 + #
  211 + #CustomLog "logs/access_log" common
  212 +
  213 + #
  214 + # If you prefer a logfile with access, agent, and referer information
  215 + # (Combined Logfile Format) you can use the following directive.
  216 + #
  217 + CustomLog "logs/access_log" combined
  218 +</IfModule>
  219 +
  220 +<IfModule alias_module>
  221 + #
  222 + # Redirect: Allows you to tell clients about documents that used to
  223 + # exist in your server's namespace, but do not anymore. The client
  224 + # will make a new request for the document at its new location.
  225 + # Example:
  226 + # Redirect permanent /foo http://www.example.com/bar
  227 +
  228 + #
  229 + # Alias: Maps web paths into filesystem paths and is used to
  230 + # access content that does not live under the DocumentRoot.
  231 + # Example:
  232 + # Alias /webpath /full/filesystem/path
  233 + #
  234 + # If you include a trailing / on /webpath then the server will
  235 + # require it to be present in the URL. You will also likely
  236 + # need to provide a <Directory> section to allow access to
  237 + # the filesystem path.
  238 +
  239 + #
  240 + # ScriptAlias: This controls which directories contain server scripts.
  241 + # ScriptAliases are essentially the same as Aliases, except that
  242 + # documents in the target directory are treated as applications and
  243 + # run by the server when requested rather than as documents sent to the
  244 + # client. The same rules about trailing "/" apply to ScriptAlias
  245 + # directives as to Alias.
  246 + #
  247 + ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
  248 +
  249 +</IfModule>
  250 +
  251 +#
  252 +# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
  253 +# CGI directory exists, if you have that configured.
  254 +#
  255 +<Directory "/var/www/cgi-bin">
  256 + AllowOverride None
  257 + Options None
  258 + Require all granted
  259 +</Directory>
  260 +
  261 +<IfModule mime_module>
  262 + #
  263 + # TypesConfig points to the file containing the list of mappings from
  264 + # filename extension to MIME-type.
  265 + #
  266 + TypesConfig /etc/mime.types
  267 +
  268 + #
  269 + # AddType allows you to add to or override the MIME configuration
  270 + # file specified in TypesConfig for specific file types.
  271 + #
  272 + #AddType application/x-gzip .tgz
  273 + #
  274 + # AddEncoding allows you to have certain browsers uncompress
  275 + # information on the fly. Note: Not all browsers support this.
  276 + #
  277 + #AddEncoding x-compress .Z
  278 + #AddEncoding x-gzip .gz .tgz
  279 + #
  280 + # If the AddEncoding directives above are commented-out, then you
  281 + # probably should define those extensions to indicate media types:
  282 + #
  283 + AddType application/x-compress .Z
  284 + AddType application/x-gzip .gz .tgz
  285 +
  286 + #
  287 + # AddHandler allows you to map certain file extensions to "handlers":
  288 + # actions unrelated to filetype. These can be either built into the server
  289 + # or added with the Action directive (see below)
  290 + #
  291 + # To use CGI scripts outside of ScriptAliased directories:
  292 + # (You will also need to add "ExecCGI" to the "Options" directive.)
  293 + #
  294 + #AddHandler cgi-script .cgi
  295 +
  296 + # For type maps (negotiated resources):
  297 + #AddHandler type-map var
  298 +
  299 + #
  300 + # Filters allow you to process content before it is sent to the client.
  301 + #
  302 + # To parse .shtml files for server-side includes (SSI):
  303 + # (You will also need to add "Includes" to the "Options" directive.)
  304 + #
  305 + AddType text/html .shtml
  306 + AddOutputFilter INCLUDES .shtml
  307 +</IfModule>
  308 +
  309 +#
  310 +# Specify a default charset for all content served; this enables
  311 +# interpretation of all content as UTF-8 by default. To use the
  312 +# default browser choice (ISO-8859-1), or to allow the META tags
  313 +# in HTML content to override this choice, comment out this
  314 +# directive:
  315 +#
  316 +AddDefaultCharset UTF-8
  317 +
  318 +<IfModule mime_magic_module>
  319 + #
  320 + # The mod_mime_magic module allows the server to use various hints from the
  321 + # contents of the file itself to determine its type. The MIMEMagicFile
  322 + # directive tells the module where the hint definitions are located.
  323 + #
  324 + conf/magic
  325 +</IfModule>
  326 +
  327 +#
  328 +# Customizable error responses come in three flavors:
  329 +# 1) plain text 2) local redirects 3) external redirects
  330 +#
  331 +# Some examples:
  332 +#ErrorDocument 500 "The server made a boo boo."
  333 +#ErrorDocument 404 /missing.html
  334 +#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
  335 +#ErrorDocument 402 http://www.example.com/subscription_info.html
  336 +#
  337 +
  338 +#
  339 +# EnableMMAP and EnableSendfile: On systems that support it,
  340 +# memory-mapping or the sendfile syscall may be used to deliver
  341 +# files. This usually improves server performance, but must
  342 +# be turned off when serving from networked-mounted
  343 +# filesystems or if support for these functions is otherwise
  344 +# broken on your system.
  345 +# Defaults if commented: EnableMMAP On, EnableSendfile Off
  346 +#
  347 +#EnableMMAP off
  348 +EnableSendfile on
  349 +
  350 +# Supplemental configuration
  351 +#
  352 +# Load config files in the "/etc/httpd/conf.d" directory, if any.
  353 + conf.d/*.conf
  354 +
  355 +LoadModule wsgi_module "/usr/lib64/httpd/modules/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so"
  356 + "/var/gdal"
  357 +
  358 + / /usr/src/app/run.wsgi
  359 +<Directory /usr/>
  360 + Require all granted
  361 +</Directory>
  1 +#! /bin/sh
  2 +
  3 +#停止容器
  4 +echo "正在关闭容器..."
  5 +docker stop dmapmanager
  6 +docker rm dmapmanager
  7 +
  8 +curPath=$(readlink -f $(dirname $0))
  9 +
  10 +
  11 +#设置日志权限
  12 +chmod -R 777 $curPath/logs/*
  13 +
  14 +#设置端口
  15 +port=""
  16 +if [ ! -n "$1" ] ;then
  17 +port="8840"
  18 +echo "未设置端口,使用默认8840端口..."
  19 +else
  20 +port=$1
  21 +echo "端口设置为$1 ..."
  22 +fi
  23 +
  24 +#启动容器和apache
  25 +echo "正在启动容器..."
  26 +set="--privileged=true -e TZ="Asia/Shanghai" --restart=always -e ALLOW_IP_RANGE=0.0.0.0/0"
  27 +docker run -d --name dmapmanager $set -p $port:80 -v $curPath:/usr/src/app -v $curPath/httpd.conf:/etc/httpd/conf/httpd.conf dci/dmapdms:4.0 /usr/sbin/init
  28 +docker exec -d dmapmanager systemctl start httpd
  29 +sleep 5
  30 +curl localhost:$port/release
1 -#! /bin/sh  
2 -  
3 -#停止容器  
4 -echo "正在关闭容器..."  
5 -docker stop apache  
6 -docker rm apache  
7 -  
8 -curPath=$(readlink -f $(dirname $0))  
9 -  
10 -#寻找模块  
11 -echo "在modules下寻找模块..."  
12 -map=""  
13 -for mod in $(ls $curPath/modules)  
14 -do  
15 - map="$map -v $curPath/modules/$mod:/usr/src/$mod"  
16 -done  
17 -  
18 -#设置日志权限  
19 -for mod in $(ls $curPath/modules)  
20 -do  
21 - chmod -R 777 $curPath/modules/$mod/logs/*  
22 -done  
23 -  
24 -  
25 -#设置端口  
26 -port=""  
27 -if [ ! -n "$1" ] ;then  
28 - port="8888"  
29 - echo "未设置端口,使用默认8888端口..."  
30 -else  
31 - port=$1  
32 - echo "端口设置为$1 ..."  
33 -fi  
34 -  
35 -#修改httpd.conf  
36 -echo "正在修改httpd.conf..."  
37 -rm $curPath/httpd.conf  
38 -cp $curPath/httpd.conf.sample $curPath/httpd.conf  
39 -echo "<VirtualHost *>" >> $curPath/httpd.conf  
40 -echo " ServerName apacheflask">>$curPath/httpd.conf  
41 -echo " WSGIDaemonProcess yourapplication user=chinadci group=chinadci threads=5">>$curPath/httpd.conf  
42 -  
43 -for mod in $(ls $curPath/modules)  
44 -do  
45 - echo " WSGIScriptAlias /$mod /usr/src/$mod/run.wsgi">>$curPath/httpd.conf  
46 -done  
47 -  
48 -echo " <Directory /usr/src/app>">>$curPath/httpd.conf  
49 -echo " WSGIProcessGroup yourapplication">>$curPath/httpd.conf  
50 -echo " WSGIApplicationGroup %{GLOBAL}">>$curPath/httpd.conf  
51 -echo " Require all granted">>$curPath/httpd.conf  
52 -echo " </Directory>">>$curPath/httpd.conf  
53 -echo "</VirtualHost>">>$curPath/httpd.conf  
54 -  
55 -#启动容器和apache  
56 -echo "正在启动容器..."  
57 -set="--privileged=true -e TZ="Asia/Shanghai" --restart=always -e ALLOW_IP_RANGE=0.0.0.0/0"  
58 -docker run -d --name apache $set -p $port:80 $map -v $curPath/httpd.conf:/etc/httpd/conf/httpd.conf dci/apache:1.0 /usr/sbin/init  
59 -docker exec -d apache systemctl start httpd  
60 -  
注册登录 后发表评论