提交 7df189622f3c5e2acb057ca35b26cd99cc408070

作者 nheweijun
1 个父辈 f1f7116b

从3.0整合新功能

... ... @@ -8,15 +8,17 @@ from app.models import Database,db,DES,Table,Columns,TableVacuate
8 8 import uuid
9 9 from . import database_test
10 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 12 from sqlalchemy.orm import Session
13 13 from sqlalchemy import create_engine
14 14 from sqlalchemy.orm import sessionmaker
15 15 from app.util.component.ApiTemplate import ApiTemplate
16 16 from app.util.component.PGUtil import PGUtil
  17 +from app.util.component.SQLUtil import SQLUtil
17 18 from app.util.component.GeometryAdapter import GeometryAdapter
  19 +from app.util.component.StructuredPrint import StructurePrint
18 20 class Api(ApiTemplate):
19   - api_name = "数据库注册"
  21 + api_name = "注册数据库"
20 22 def process(self):
21 23 res ={}
22 24 res["result"] = False
... ... @@ -29,7 +31,7 @@ class Api(ApiTemplate):
29 31 encryption = int(self.para.get("encryption","0"))
30 32 if encryption:
31 33 passwd = DES.decode(passwd)
32   -
  34 +
33 35 sqlalchemy_uri = "postgresql://{}:{}@{}:{}/{}".format(user,passwd,host,port,database)
34 36 connectsrt = "hostaddr={} port={} dbname='{}' user='{}' password='{}'".format(host,port,database,user,passwd)
35 37
... ... @@ -87,26 +89,29 @@ class Api(ApiTemplate):
87 89
88 90 def register_table(self,database):
89 91 this_time = datetime.datetime.now()
  92 +
90 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 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 109 spatial_table_name =[]
106 110 tables=[]
107 111 for i in range(pg_ds.GetLayerCount()):
108 112 layer: Layer = pg_ds.GetLayer(i)
109 113 l_name = layer.GetName()
  114 +
110 115 # 只注册public的空间表,其他表空间的表名会有.
111 116 if layer.GetName().__contains__("."):
112 117 continue
... ... @@ -116,9 +121,15 @@ class Api(ApiTemplate):
116 121 spatial_table_name.append(layer.GetName())
117 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 129 # 范围统计和数量统计以100w为界限
120 130 query_count_layer: Layer = pg_ds.ExecuteSQL(
121 131 '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(l_name))
  132 +
122 133 feature_count = query_count_layer.GetFeature(0).GetField("ec")
123 134 # 要素少于100w可以精确统计
124 135 if feature_count < 1000000:
... ... @@ -137,11 +148,13 @@ class Api(ApiTemplate):
137 148
138 149 table_guid = uuid.uuid1().__str__()
139 150
  151 + geom_type = GeometryAdapter.get_geometry_type(layer)
  152 +
140 153 table = Table(guid=table_guid,
141 154 database_guid=database.guid,
142 155 # alias=layer.GetName(),
143 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 158 extent=extent,
146 159 feature_count=feature_count
147 160 )
... ... @@ -164,19 +177,26 @@ class Api(ApiTemplate):
164 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 182 db_session: Session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri))
170 183
171 184 # 只注册public中的表
172 185 result = db_session.execute(
173 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 188 for re in result:
175 189 table_name = re[0]
176 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 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 201 table = Table(guid=table_guid,
182 202 database_guid=database.guid,
... ... @@ -209,15 +229,26 @@ class Api(ApiTemplate):
209 229 column = Columns(guid=uuid.uuid1().__str__(), table_guid=table_guid,
210 230 name=col[1], create_time=this_time, update_time=this_time)
211 231 db.session.add(column)
  232 + db_session.commit()
212 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 239 for i in range(pg_ds.GetLayerCount()):
218 240 layer:Layer = pg_ds.GetLayer(i)
219 241 l_name = layer.GetName()
  242 +
  243 +
  244 +
220 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 252 base_layer_name=l_name.split("_vacuate_")[0]
222 253 level = l_name.split("_")[-2]
223 254 pixel_distance_str: str ="0"
... ... @@ -227,15 +258,17 @@ class Api(ApiTemplate):
227 258 pixel_distance_str="0.{}".format(pixel_distance_str)
228 259 except:
229 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 280 engine = create_engine(sqlachemy_uri)
248 281 system_session = sessionmaker(bind=engine)()
249 282 system_session.execute(test_sql).fetchone()
250   -
251 283 except:
252 284 check = False
253 285 finally:
... ... @@ -281,10 +313,6 @@ class Api(ApiTemplate):
281 313 {"name": "alias",
282 314 "in": "formData",
283 315 "type": "string","description":"数据库别名","required": "true"},
284   -
285   - {"name": "encryption",
286   - "in": "formData",
287   - "type": "integer", "description": "密码是否加密", "enum": [0,1]},
288 316 ],
289 317 "responses":{
290 318 200:{
... ...
... ... @@ -8,28 +8,28 @@ from app.models import *
8 8
9 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 13 import os
14 14 import uuid
15 15 import configure
16 16 from app.util.component.ApiTemplate import ApiTemplate
17 17 from app.util.component.PGUtil import PGUtil
18 18 from app.util.component.ZipUtil import ZipUtil
  19 +
19 20 class Api(ApiTemplate):
20 21
21   - api_name = "下载数据"
22 22 def process(self):
23 23 #获取参数
24 24
25 25 #返回结果
26   - res={}
  26 + result={}
27 27 #设置编码
28 28 encoding = self.para.get("encoding")
29 29 if encoding:
30 30 gdal.SetConfigOption("SHAPE_ENCODING",encoding)
31 31 else:
32   - gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
  32 + gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8")
33 33
34 34 ds:DataSource = None
35 35 try:
... ... @@ -38,6 +38,7 @@ class Api(ApiTemplate):
38 38 database = Database.query.filter_by(guid=database_guid).one_or_none()
39 39 if not database:
40 40 raise Exception("数据库不存在!")
  41 +
41 42
42 43 ds:DataSource = PGUtil.open_pg_data_source(0,DES.decode(database.sqlalchemy_uri))
43 44
... ... @@ -49,16 +50,16 @@ class Api(ApiTemplate):
49 50 if download_type.__eq__("gdb"):
50 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 55 except Exception as e:
55 56 print(traceback.format_exc())
56   - res["msg"]= e.__str__()
57   - res["result"]=False
  57 + result["message"]= e.__str__()
  58 + result["state"]=-1
58 59 finally:
59 60 if ds:
60 61 ds.Destroy()
61   - return res
  62 + return result
62 63
63 64
64 65 def download_shp(self,table_names,ds):
... ... @@ -77,9 +78,23 @@ class Api(ApiTemplate):
77 78 dirpath = os.path.join(parent, "file_tmp", uuid_)
78 79 os.makedirs(dirpath)
79 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 93 data_source.Destroy()
  94 +
  95 +
82 96 ZipUtil.create_zip(os.path.join(parent, "file_tmp", table_name+"_"+uuid_) + ".zip", [dirpath])
  97 +
83 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 129 # if not table_alias:
115 130 # table_alias = table_name
116 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 154 gdb_ds.Destroy()
121 155 ZipUtil.create_zip(gdb_path + ".zip", [gdb_path])
122 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 159 return data
126 160
... ...
... ... @@ -18,6 +18,10 @@ from . import table_refresh
18 18 from . import table_delete
19 19 from . import table_view
20 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 25 class DataManager(BlueprintApi):
22 26
23 27 bp = Blueprint("DataManager", __name__, url_prefix="/API/Manager")
... ... @@ -106,4 +110,41 @@ class DataManager(BlueprintApi):
106 110 """
107 111 数据抽稀
108 112 """
109   - return table_vacuate.Api().result
\ No newline at end of file
  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
\ No newline at end of file
... ...
... ... @@ -40,6 +40,10 @@ class Api(ApiTemplate):
40 40 tables = Table.query.order_by(Table.update_time.desc(),Table.name)
41 41 else:
42 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 47 if database_guid:
44 48 tables = tables.filter_by(database_guid=database_guid)
45 49 if catalog_guid:
... ...
... ... @@ -13,7 +13,7 @@ import datetime
13 13 import uuid
14 14
15 15 from sqlalchemy.orm import Session
16   -
  16 +from app.util.component.SQLUtil import SQLUtil
17 17 from app.util.component.PGUtil import PGUtil
18 18 from app.util.component.ModelVisitor import ModelVisitor
19 19 from app.util.component.StructuredPrint import StructurePrint
... ... @@ -70,6 +70,8 @@ class Api(ApiTemplate):
70 70 data_session=None
71 71 result = {}
72 72 sys_session = None
  73 + db_tuple = PGUtil.get_info_from_sqlachemy_uri(DES.decode(database.sqlalchemy_uri))
  74 +
73 75 try:
74 76 sys_session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI)
75 77
... ... @@ -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 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 106 sys_session.commit()
... ... @@ -133,11 +135,11 @@ class Api(ApiTemplate):
133 135 # 增加新普通表
134 136
135 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 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 144 sys_session.commit()
143 145 result["data"] = "刷新数据成功!"
... ... @@ -168,7 +170,7 @@ class Api(ApiTemplate):
168 170 sys_session.close()
169 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 176 :param database:
... ... @@ -196,10 +198,17 @@ class Api(ApiTemplate):
196 198 if layer.GetName().__contains__("_vacuate_"):
197 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 207 # 范围统计和数量统计以100w为界限
200 208 query_count_layer: Layer = pg_ds.ExecuteSQL(
201 209 '''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(
202 210 l_name))
  211 +
203 212 feature_count = query_count_layer.GetFeature(0).GetField("ec")
204 213 # 要素少于100w可以精确统计
205 214 if feature_count < 1000000:
... ... @@ -218,12 +227,14 @@ class Api(ApiTemplate):
218 227
219 228 StructurePrint.print("空间表增加!")
220 229
  230 + geom_type = GeometryAdapter.get_geometry_type(layer)
  231 +
221 232 table_guid = uuid.uuid1().__str__()
222 233 table = Table(guid=table_guid,
223 234 database_guid=database.guid,
224 235 # alias=layer.GetName(),
225 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 238 extent=extent,
228 239 feature_count=feature_count
229 240 )
... ... @@ -240,7 +251,7 @@ class Api(ApiTemplate):
240 251 sys_session.add(column)
241 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 257 for i in range(pg_ds.GetLayerCount()):
... ... @@ -255,6 +266,10 @@ class Api(ApiTemplate):
255 266 if layer.GetName().__contains__("_vacuate_"):
256 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 274 base_layer_name = l_name.split("_vacuate_")[0]
260 275 level = l_name.split("_")[-2]
... ... @@ -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 305 for table in spatial_tables:
289 306
... ... @@ -303,6 +320,12 @@ class Api(ApiTemplate):
303 320 if layer.GetName().__contains__("_vacuate_"):
304 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 329 columns = table.relate_columns
307 330 columns_names = [column.name for column in columns]
308 331 feature_defn: FeatureDefn = layer.GetLayerDefn()
... ... @@ -357,11 +380,18 @@ class Api(ApiTemplate):
357 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 384 for table_name in real_common_tables_name:
362 385 if table_name not in origin_common_tables_name:
363 386 StructurePrint.print("{}非空间表增加!".format(table_name))
364 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 395 count = data_session.execute('select count(*) from "{}"'.format(table_name)).fetchone()[0]
366 396
367 397 table = Table(guid=table_guid,
... ... @@ -402,7 +432,7 @@ class Api(ApiTemplate):
402 432 for table in tables:
403 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 436 for table_name in origin_common_tables_name:
407 437 tables = sys_session.query(Table).filter_by(name=table_name).filter_by(database_guid=database_guid).all()
408 438 for table in tables:
... ... @@ -411,6 +441,13 @@ class Api(ApiTemplate):
411 441 sys_session.delete(table)
412 442 # 修改表
413 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 451 columns = table.relate_columns
415 452 columns_names = [column.name for column in columns]
416 453
... ... @@ -448,15 +485,15 @@ class Api(ApiTemplate):
448 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 493 if not table.feature_count.__eq__(count):
455 494 StructurePrint.print("{}表要素变化!".format(table_name))
456 495 sys_session.query(Table).filter_by(guid=table.guid).update({"feature_count": count})
457 496
458   -
459   -
460 497
461 498 api_doc={
462 499 "tags":["管理接口"],
... ...
... ... @@ -5,19 +5,23 @@
5 5
6 6 import datetime
7 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 10 from sqlalchemy.engine import ResultProxy
11 11 from app.util.component.ApiTemplate import ApiTemplate
12 12 from app.util.component.PGUtil import PGUtil
13 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 16 import multiprocessing
15 17 import uuid
16 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 25 def process(self):
22 26
23 27 res = {}
... ... @@ -26,15 +30,21 @@ class Api(ApiTemplate):
26 30 try:
27 31 table_guid = self.para.get("guid")
28 32 table: Table = Table.query.filter_by(guid=table_guid).one_or_none()
  33 +
29 34 if not table:
30 35 raise Exception("数据不存在!")
31 36
32   - # 判断图层是否存在
33   -
34 37 pg_ds :DataSource= PGUtil.open_pg_data_source(0,DES.decode(table.relate_database.sqlalchemy_uri))
35 38 layer = pg_ds.GetLayerByName(table.name)
  39 + # 判断图层是否存在
36 40 if not layer:
37 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 48 if pg_ds:
39 49 pg_ds.Destroy()
40 50
... ... @@ -46,17 +56,22 @@ class Api(ApiTemplate):
46 56 res["result"] = False
47 57 res["msg"] = "非空间表!"
48 58 return res
  59 +
49 60 # if table.is_vacuate==1:
50 61 # res["state"] = -1
51 62 # res["message"] = "已精化!"
52 63 # return res
53 64
54 65
  66 +
55 67 # 初始化task
56 68 task_guid = uuid.uuid1().__str__()
57 69 vacuate_process = multiprocessing.Process(target=self.task,args=(table,task_guid))
58 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 76 task = Task(guid=task_guid,
62 77 name="{}精化".format(table.name),
... ... @@ -67,12 +82,15 @@ class Api(ApiTemplate):
67 82 creator=self.para.get("creator"),
68 83 file_name=None,
69 84 database_guid=table.database_guid,
70   - process="精化中")
  85 + process="精化中",
  86 + parameter=",".join([str(x) for x in ref_grids]))
  87 +
71 88 db.session.add(task)
72 89 db.session.commit()
73 90 res["msg"] = "图层抽稀已提交!"
74   - res["data"] = table_guid
  91 + res["data"] = task_guid
75 92 res["result"] = True
  93 +
76 94 except Exception as e:
77 95 raise e
78 96 finally:
... ... @@ -87,23 +105,34 @@ class Api(ApiTemplate):
87 105 pg_ds = None
88 106 vacuate_process = None
89 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 109 sys_session.query(Table).filter_by(guid=table.guid).update(
94 110 {"is_vacuate": 2, "update_time": datetime.datetime.now()})
95 111 sys_session.commit()
96 112
  113 +
97 114 database = sys_session.query(Database).filter_by(guid=table.database_guid).one_or_none()
98 115 pg_session = PGUtil.get_db_session(DES.decode(database.sqlalchemy_uri))
99 116
100 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 130 options = ["OVERWRITE=yes", "GEOMETRY_NAME={}".format(PGUtil.get_geo_column(table.name,pg_session)),
104 131 "PRECISION=NO"]
  132 +
105 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 138 for feature in layer:
... ... @@ -112,14 +141,28 @@ class Api(ApiTemplate):
112 141 if geo is not None:
113 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 158 sys_session.query(Table).filter_by(guid=table.guid).update(
117 159 {"is_vacuate": 1, "update_time": datetime.datetime.now()})
118 160 sys_session.commit()
119 161
120 162 except Exception as e:
121 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 166 sys_session.query(Table).filter_by(guid=table.guid).update(
124 167 {"is_vacuate": 0, "update_time": datetime.datetime.now()})
125 168
... ... @@ -129,7 +172,8 @@ class Api(ApiTemplate):
129 172 task_guid=task_guid)
130 173 sys_session.add(task_process)
131 174 sys_session.commit()
132   - vacuate_process.rollback()
  175 + if vacuate_process:
  176 + vacuate_process.rollback()
133 177
134 178 print(traceback.format_exc())
135 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 + }
\ No newline at end of file
... ...
  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()
\ No newline at end of file
... ...
  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 16 import traceback
17 17 import copy
18 18 from app.util.component.GeometryAdapter import GeometryAdapter
  19 +from app.util.component.VacuateConf import VacuateConf
19 20 class EntryDataVacuate:
20 21
21 22 def entry(self,parameter):
... ... @@ -317,13 +318,15 @@ class ThisTask:
317 318 else:
318 319 ext = [round(e, 2) for e in ext]
319 320
  321 + geom_type = GeometryAdapter.get_geometry_type(layer)
  322 +
320 323 extent = "{},{},{},{}".format(ext[0], ext[1], ext[2], ext[3])
321 324 table_guid = uuid.uuid1().__str__()
322 325 table = Table(guid=table_guid,
323 326 database_guid=self.database.guid,
324 327 creator=creator,
325 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 330 extent=extent,
328 331 feature_count=layer.GetFeatureCount(),
329 332 is_vacuate=is_vacuate
... ... @@ -353,13 +356,16 @@ class ThisTask:
353 356 # 抽稀表有固定的命名规则
354 357 for level,layer in vacuate_layers.items():
355 358 pixel_distance_str:str=layer.GetName().split("_")[-1]
  359 + lev = layer.GetName().split("_")[-2]
  360 +
356 361 if pixel_distance_str.startswith("0"):
357 362 pixel_distance_str="0.{}".format(pixel_distance_str)
358 363
359 364 pixel_distance = float(pixel_distance_str)
  365 +
360 366 table_vacuate = TableVacuate(guid=uuid.uuid1().__str__(),
361 367 table_guid=table_guid,
362   - level=level,
  368 + level=int(lev),
363 369 name=layer.GetName(),
364 370 pixel_distance=pixel_distance)
365 371 self.sys_session.add(table_vacuate)
... ... @@ -398,14 +404,18 @@ class VacuateProcess:
398 404 vacuate_layers_gridsize={}
399 405 pg_ds_dict = {}
400 406 # 图层要素大于5W才抽稀
401   - least_vacuate_count = 20000
  407 + least_vacuate_count = VacuateConf.least_vacuate_count
402 408
403 409 extent=[]
404 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 419 this_gridsize=[]
410 420
411 421
... ... @@ -453,17 +463,17 @@ class VacuateProcess:
453 463 ######
454 464
455 465 if extent[0]>180:
456   - t_grid_size=self.project_gridsize
  466 + self.t_grid_size=self.project_gridsize
457 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 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 477 print(grid_size)
468 478 self.this_gridsize.append(grid_size)
469 479 self.max_level += 1
... ... @@ -479,6 +489,7 @@ class VacuateProcess:
479 489 # 生成抽稀图层
480 490 options = options[1:]
481 491 options.append("OVERWRITE=yes")
  492 + options.append("LAUNDER=no")
482 493 for l in range(self.max_level):
483 494 this_grid_len = self.this_gridsize[l]
484 495
... ... @@ -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 512 ogr.wkbUnknown, options)
501 513 # 抽稀表不需要属性
502 514 # vl.CreateFields(schema)
... ...
... ... @@ -5,8 +5,6 @@
5 5 from osgeo import ogr
6 6 from sqlalchemy import create_engine
7 7 from sqlalchemy.orm import sessionmaker,Session
8   -from sqlalchemy.engine import ResultProxy
9   -
10 8 class PGUtil:
11 9
12 10 @classmethod
... ... @@ -27,11 +25,6 @@ class PGUtil:
27 25
28 26 @classmethod
29 27 def get_info_from_sqlachemy_uri(cls,uri):
30   - '''
31   - 解析sqlachemy_uri
32   - :param uri:
33   - :return:
34   - '''
35 28 parts = uri.split(":")
36 29 user = parts[1][2:]
37 30
... ... @@ -56,12 +49,7 @@ class PGUtil:
56 49
57 50 @classmethod
58 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 53 geom_col_sql = '''
66 54 SELECT a.attname AS field,t.typname AS type
67 55 FROM
... ... @@ -75,7 +63,7 @@ class PGUtil:
75 63 and a.atttypid = t.oid
76 64 '''.format(table_name)
77 65 geom_col = None
78   - geom_result: ResultProxy = db_session.execute(geom_col_sql)
  66 + geom_result = db_session.execute(geom_col_sql)
79 67 for row_proxy in geom_result:
80 68 if row_proxy[1].__eq__("geometry"):
81 69 geom_col = row_proxy[0]
... ... @@ -84,39 +72,39 @@ class PGUtil:
84 72
85 73 @classmethod
86 74 def get_table_count(cls,table_name,db_session):
87   - '''
88   - 获取图层数量
89   - :param table_name:
90   - :param db_session:
91   - :return:
92   - '''
93 75 count_result = db_session.execute('''SELECT reltuples::bigint AS ec FROM pg_class WHERE oid = 'public."{}"'::regclass'''.format(
94 76 table_name)).fetchone()
95 77 count = count_result[0]
96 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 80 count=count_result[0]
99 81 return count
100 82
101 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 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
\ No newline at end of file
... ...
... ... @@ -8,11 +8,45 @@ class SQLUtil:
8 8
9 9
10 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 18 return count
14 19
15 20 @classmethod
16 21 def rename(cls,session,origin,after_name):
17 22 rename_sql = 'alter table "{}" rename to "{}"'.format(origin, after_name)
18 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
\ No newline at end of file
... ...
  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]
\ No newline at end of file
... ...
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>
\ No newline at end of file
  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   -
注册登录 后发表评论