正在显示
16 个修改的文件
包含
296 行增加
和
38 行删除
@@ -94,6 +94,11 @@ def create_app(): | @@ -94,6 +94,11 @@ def create_app(): | ||
94 | # 不检测https | 94 | # 不检测https |
95 | os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' | 95 | os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' |
96 | 96 | ||
97 | + | ||
98 | + @app.before_first_request | ||
99 | + def init_data(): | ||
100 | + pass | ||
101 | + | ||
97 | # start_schedule() | 102 | # start_schedule() |
98 | return app | 103 | return app |
99 | 104 |
@@ -23,7 +23,6 @@ class Api(ApiTemplate): | @@ -23,7 +23,6 @@ class Api(ApiTemplate): | ||
23 | res["result"] = False | 23 | res["result"] = False |
24 | try: | 24 | try: |
25 | # 业务逻辑 | 25 | # 业务逻辑 |
26 | - | ||
27 | if not Database.query.filter_by(guid=self.para.get("database_guid")).one_or_none(): | 26 | if not Database.query.filter_by(guid=self.para.get("database_guid")).one_or_none(): |
28 | res["msg"]="数据库不存在!" | 27 | res["msg"]="数据库不存在!" |
29 | return res | 28 | return res |
@@ -86,7 +86,7 @@ class Api(ApiTemplate): | @@ -86,7 +86,7 @@ class Api(ApiTemplate): | ||
86 | task_writer = TaskWriter(task_guid) | 86 | task_writer = TaskWriter(task_guid) |
87 | 87 | ||
88 | #进入创建金字塔的状态 | 88 | #进入创建金字塔的状态 |
89 | - task_guid.sys_session.query(Image).filter_by(guid=image_guid).update({"has_pyramid": -1}) | 89 | + task_writer.session.query(Image).filter_by(guid=image_guid).update({"has_pyramid": -1}) |
90 | task_writer.update_task({"state": 2}) | 90 | task_writer.update_task({"state": 2}) |
91 | 91 | ||
92 | #所有数据节点的影像都要建金字塔 | 92 | #所有数据节点的影像都要建金字塔 |
@@ -155,6 +155,7 @@ class ImageWMTSServer(ImageServer): | @@ -155,6 +155,7 @@ class ImageWMTSServer(ImageServer): | ||
155 | if not tile_scheme: | 155 | if not tile_scheme: |
156 | raise Exception("切片方案不存在!") | 156 | raise Exception("切片方案不存在!") |
157 | tile_scheme = ModelVisitor.object_to_json(tile_scheme) | 157 | tile_scheme = ModelVisitor.object_to_json(tile_scheme) |
158 | + | ||
158 | xml = '''<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0"> | 159 | xml = '''<Capabilities xmlns="http://www.opengis.net/wmts/1.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd" version="1.0.0"> |
159 | <!-- Service Identification --> | 160 | <!-- Service Identification --> |
160 | <ows:ServiceIdentification> | 161 | <ows:ServiceIdentification> |
@@ -137,7 +137,11 @@ class ImageService(db.Model): | @@ -137,7 +137,11 @@ class ImageService(db.Model): | ||
137 | __tablename__ = 'dmap_image_service' | 137 | __tablename__ = 'dmap_image_service' |
138 | guid = Column(String(256), primary_key=True) | 138 | guid = Column(String(256), primary_key=True) |
139 | name = Column(String,unique = True) | 139 | name = Column(String,unique = True) |
140 | + #切片方案 | ||
141 | + scheme = Column(Text) | ||
142 | + | ||
140 | scheme_guid = Column(String) | 143 | scheme_guid = Column(String) |
144 | + | ||
141 | extent = Column(String(256)) | 145 | extent = Column(String(256)) |
142 | # node = Column(Integer) | 146 | # node = Column(Integer) |
143 | #可视范围geojson | 147 | #可视范围geojson |
@@ -173,9 +177,7 @@ class ImageTag(db.Model): | @@ -173,9 +177,7 @@ class ImageTag(db.Model): | ||
173 | images = db.relationship('Image', | 177 | images = db.relationship('Image', |
174 | secondary=dmap_image_tag_rel, | 178 | secondary=dmap_image_tag_rel, |
175 | backref='image_tags', | 179 | backref='image_tags', |
176 | - lazy='dynamic' | ||
177 | - ) | ||
178 | - | 180 | + lazy='dynamic') |
179 | 181 | ||
180 | class TileService(db.Model): | 182 | class TileService(db.Model): |
181 | ''' | 183 | ''' |
@@ -217,6 +219,9 @@ class TileService(db.Model): | @@ -217,6 +219,9 @@ class TileService(db.Model): | ||
217 | #图层描述 | 219 | #图层描述 |
218 | layer_description = Column(String) | 220 | layer_description = Column(String) |
219 | 221 | ||
222 | + #切片方案 | ||
223 | + scheme = Column(Text) | ||
224 | + | ||
220 | scheme_guid = Column(String,ForeignKey('dmap_tile_scheme.guid')) | 225 | scheme_guid = Column(String,ForeignKey('dmap_tile_scheme.guid')) |
221 | service_guid = Column(String,ForeignKey('dmap_service.guid')) | 226 | service_guid = Column(String,ForeignKey('dmap_service.guid')) |
222 | 227 |
@@ -68,6 +68,12 @@ class Api(ApiTemplate): | @@ -68,6 +68,12 @@ class Api(ApiTemplate): | ||
68 | "in": "formData", | 68 | "in": "formData", |
69 | "type": "string", | 69 | "type": "string", |
70 | "description": "[切片服务,影像服务]切片方案"}, | 70 | "description": "[切片服务,影像服务]切片方案"}, |
71 | + | ||
72 | + {"name": "scheme_guid", | ||
73 | + "in": "formData", | ||
74 | + "type": "string", | ||
75 | + "description": "[切片服务,影像服务]切片方案"}, | ||
76 | + | ||
71 | {"name": "functions", | 77 | {"name": "functions", |
72 | "in": "formData", | 78 | "in": "formData", |
73 | "type": "string", | 79 | "type": "string", |
@@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
7 | from flasgger import swag_from | 7 | from flasgger import swag_from |
8 | from flask import Blueprint | 8 | from flask import Blueprint |
9 | from app.util import BlueprintApi | 9 | from app.util import BlueprintApi |
10 | -from . import upload_oview,tile_service_register,tile_service_edit | 10 | +from . import upload_oview,tile_service_register,tile_service_edit,tile_service_reload |
11 | 11 | ||
12 | 12 | ||
13 | 13 | ||
@@ -45,3 +45,12 @@ class DataManager(BlueprintApi): | @@ -45,3 +45,12 @@ class DataManager(BlueprintApi): | ||
45 | """ | 45 | """ |
46 | return tile_service_edit.Api().result | 46 | return tile_service_edit.Api().result |
47 | 47 | ||
48 | + @staticmethod | ||
49 | + @bp.route('/Reload', methods=['GET']) | ||
50 | + @swag_from(tile_service_reload.Api.api_doc) | ||
51 | + def api_tile_service_reload(): | ||
52 | + """ | ||
53 | + TileService Reload | ||
54 | + """ | ||
55 | + return tile_service_reload.Api().result | ||
56 | + |
@@ -4,11 +4,15 @@ | @@ -4,11 +4,15 @@ | ||
4 | #email: nheweijun@sina.com | 4 | #email: nheweijun@sina.com |
5 | 5 | ||
6 | from app.util.component.ApiTemplate import ApiTemplate | 6 | from app.util.component.ApiTemplate import ApiTemplate |
7 | +from app.util.component.ModelVisitor import ModelVisitor | ||
7 | import uuid | 8 | import uuid |
8 | from ..models import TileService,Service,db,ServiceFunction | 9 | from ..models import TileService,Service,db,ServiceFunction |
10 | +import datetime | ||
11 | +import requests | ||
12 | +from .util.ProjectFile import ProjectFile | ||
9 | 13 | ||
14 | +from requests import Response | ||
10 | 15 | ||
11 | -import datetime | ||
12 | class Api(ApiTemplate): | 16 | class Api(ApiTemplate): |
13 | 17 | ||
14 | api_name = "修改切片服务" | 18 | api_name = "修改切片服务" |
@@ -25,7 +29,6 @@ class Api(ApiTemplate): | @@ -25,7 +29,6 @@ class Api(ApiTemplate): | ||
25 | service = Service.query.filter_by(guid=guid) | 29 | service = Service.query.filter_by(guid=guid) |
26 | this_time = datetime.datetime.now() | 30 | this_time = datetime.datetime.now() |
27 | 31 | ||
28 | - | ||
29 | service_update = {"update_time":this_time} | 32 | service_update = {"update_time":this_time} |
30 | tile_update = {} | 33 | tile_update = {} |
31 | for key in self.para.keys(): | 34 | for key in self.para.keys(): |
@@ -36,10 +39,27 @@ class Api(ApiTemplate): | @@ -36,10 +39,27 @@ class Api(ApiTemplate): | ||
36 | "layer_extent","layer_description","scheme_guid"]: | 39 | "layer_extent","layer_description","scheme_guid"]: |
37 | tile_update[key] = self.para.get(key) | 40 | tile_update[key] = self.para.get(key) |
38 | 41 | ||
39 | - tile_service = TileService.query.filter_by(service_guid=guid) | 42 | + #通知tileserver,更新缓存 |
43 | + ts = TileService.query.filter_by(service_guid=guid).one_or_none() | ||
44 | + se = service.one_or_none() | ||
40 | 45 | ||
41 | - tile_type = self.para.get("tile_type") | 46 | + ts_json = ModelVisitor.object_to_json(ts) |
47 | + ts_json.update(tile_update) | ||
48 | + project_file = ProjectFile.create(ts_json) | ||
49 | + | ||
50 | + para = {"name":self.para.get("name") if self.para.get("name") else se.name, | ||
51 | + "title":self.para.get("title") if self.para.get("title") else se.title, | ||
52 | + "type":"tileserver","capabilities":1,"project":project_file} | ||
53 | + | ||
54 | + tile_service_edit_url = "" | ||
42 | 55 | ||
56 | + resp: Response = requests.post(tile_service_edit_url,para).json() | ||
57 | + if not resp.json()["status"].__eq__("true"): | ||
58 | + raise Exception("调用切片服务的注册服务接口失败!") | ||
59 | + | ||
60 | + #修改数据库 | ||
61 | + tile_service = TileService.query.filter_by(service_guid=guid) | ||
62 | + tile_type = self.para.get("tile_type") | ||
43 | # 修改功能 | 63 | # 修改功能 |
44 | if tile_type: | 64 | if tile_type: |
45 | old_functions = ServiceFunction.query.filter_by(service_guid=guid).all() | 65 | old_functions = ServiceFunction.query.filter_by(service_guid=guid).all() |
@@ -57,8 +77,8 @@ class Api(ApiTemplate): | @@ -57,8 +77,8 @@ class Api(ApiTemplate): | ||
57 | tile_service.update(tile_update) | 77 | tile_service.update(tile_update) |
58 | 78 | ||
59 | db.session.commit() | 79 | db.session.commit() |
60 | - | ||
61 | res["result"] = True | 80 | res["result"] = True |
81 | + | ||
62 | except Exception as e: | 82 | except Exception as e: |
63 | raise e | 83 | raise e |
64 | 84 | ||
@@ -67,11 +87,14 @@ class Api(ApiTemplate): | @@ -67,11 +87,14 @@ class Api(ApiTemplate): | ||
67 | api_doc = { | 87 | api_doc = { |
68 | "tags": ["切片服务接口"], | 88 | "tags": ["切片服务接口"], |
69 | "parameters": [ | 89 | "parameters": [ |
90 | + {"name": "guid", | ||
91 | + "in": "formData", | ||
92 | + "type": "string", | ||
93 | + "description": "service guid"}, | ||
70 | 94 | ||
71 | {"name": "name", | 95 | {"name": "name", |
72 | "in": "formData", | 96 | "in": "formData", |
73 | "type": "string", | 97 | "type": "string", |
74 | - "required": "true", | ||
75 | "description": "[地图服务,切片服务,影像服务]"}, | 98 | "description": "[地图服务,切片服务,影像服务]"}, |
76 | {"name": "title", | 99 | {"name": "title", |
77 | "in": "formData", | 100 | "in": "formData", |
@@ -5,14 +5,17 @@ | @@ -5,14 +5,17 @@ | ||
5 | 5 | ||
6 | 6 | ||
7 | from app.util.component.ApiTemplate import ApiTemplate | 7 | from app.util.component.ApiTemplate import ApiTemplate |
8 | +from app.util.component.ModelVisitor import ModelVisitor | ||
8 | import uuid | 9 | import uuid |
9 | -from ..models import TileService,Service,db,ServiceFunction | 10 | +from ..models import TileService,Service,db,ServiceFunction,TileScheme |
10 | 11 | ||
11 | import datetime | 12 | import datetime |
12 | import configure | 13 | import configure |
13 | import requests | 14 | import requests |
14 | from requests import Response | 15 | from requests import Response |
15 | -import json | 16 | + |
17 | +from .util.ProjectFile import ProjectFile | ||
18 | + | ||
16 | class Api(ApiTemplate): | 19 | class Api(ApiTemplate): |
17 | 20 | ||
18 | api_name = "注册切片服务" | 21 | api_name = "注册切片服务" |
@@ -20,16 +23,20 @@ class Api(ApiTemplate): | @@ -20,16 +23,20 @@ class Api(ApiTemplate): | ||
20 | def process(self): | 23 | def process(self): |
21 | # 返回结果 | 24 | # 返回结果 |
22 | res = {} | 25 | res = {} |
23 | - | ||
24 | try: | 26 | try: |
25 | - | ||
26 | this_time = datetime.datetime.now() | 27 | this_time = datetime.datetime.now() |
27 | service_guid = uuid.uuid1().__str__() | 28 | service_guid = uuid.uuid1().__str__() |
28 | tile_service_guid = uuid.uuid1().__str__() | 29 | tile_service_guid = uuid.uuid1().__str__() |
29 | service_function_guid = uuid.uuid1().__str__() | 30 | service_function_guid = uuid.uuid1().__str__() |
30 | - | ||
31 | # 调用切片服务的注册服务接口 | 31 | # 调用切片服务的注册服务接口 |
32 | - # 先调用切片服务接口,成功后才持久化 | 32 | + project_file = ProjectFile.create(self.para) |
33 | + para = {"name":self.para.get("name"),"title":self.para.get("title"), | ||
34 | + "type":"tileserver","capabilities":1,"project":project_file} | ||
35 | + tile_service_register_url = "" | ||
36 | + | ||
37 | + resp: Response = requests.post(tile_service_register_url,para).json() | ||
38 | + if not resp.json()["status"].__eq__("true"): | ||
39 | + raise Exception("调用切片服务的注册服务接口失败!") | ||
33 | 40 | ||
34 | service = Service( | 41 | service = Service( |
35 | guid = service_guid, | 42 | guid = service_guid, |
@@ -52,6 +59,8 @@ class Api(ApiTemplate): | @@ -52,6 +59,8 @@ class Api(ApiTemplate): | ||
52 | if tile_service_isexist: | 59 | if tile_service_isexist: |
53 | db.session.delete(tile_service_isexist) | 60 | db.session.delete(tile_service_isexist) |
54 | 61 | ||
62 | + tile_scheme: TileScheme = TileScheme.query.filter_by(guid=self.para.get("scheme_guid")).one_or_none() | ||
63 | + | ||
55 | tile_service = TileService( | 64 | tile_service = TileService( |
56 | guid = tile_service_guid, | 65 | guid = tile_service_guid, |
57 | name = self.para.get("name"), | 66 | name = self.para.get("name"), |
@@ -69,8 +78,9 @@ class Api(ApiTemplate): | @@ -69,8 +78,9 @@ class Api(ApiTemplate): | ||
69 | layer_extent = self.para.get("layer_extent"), | 78 | layer_extent = self.para.get("layer_extent"), |
70 | layer_description = self.para.get("layer_description"), | 79 | layer_description = self.para.get("layer_description"), |
71 | scheme_guid = self.para.get("scheme_guid"), | 80 | scheme_guid = self.para.get("scheme_guid"), |
81 | + scheme = ModelVisitor.object_to_json(tile_scheme), | ||
72 | service_guid = service_guid, | 82 | service_guid = service_guid, |
73 | - metadata_url="{}/DMap/Services/{}/MapServer/WMTSServer".format(configure.wmts_url,self.para.get("name")) | 83 | + metadata_url = "{}/DMap/Services/{}/MapServer/WMTSServer".format(configure.wmts_url,self.para.get("name")) |
74 | ) | 84 | ) |
75 | 85 | ||
76 | service_function = ServiceFunction(guid=service_function_guid, | 86 | service_function = ServiceFunction(guid=service_function_guid, |
@@ -82,18 +92,6 @@ class Api(ApiTemplate): | @@ -82,18 +92,6 @@ class Api(ApiTemplate): | ||
82 | db.session.add(service_function) | 92 | db.session.add(service_function) |
83 | db.session.commit() | 93 | db.session.commit() |
84 | 94 | ||
85 | - # 调用切片服务的注册服务接口 | ||
86 | - try: | ||
87 | - url = "{}/dmap/api/manager/updatecache?servicename={}".format(configure.wmts_url,service.name) | ||
88 | - resp:Response = requests.get(url) | ||
89 | - if not resp.json()["status"].__eq__("true"): | ||
90 | - raise Exception("调用切片服务的注册服务接口失败!") | ||
91 | - except Exception as e: | ||
92 | - db.session.delete(service) | ||
93 | - db.session.delete(tile_service) | ||
94 | - db.session.delete(service_function) | ||
95 | - db.session.commit() | ||
96 | - raise e | ||
97 | res["data"] = service_guid | 95 | res["data"] = service_guid |
98 | res["result"] = True | 96 | res["result"] = True |
99 | except Exception as e: | 97 | except Exception as e: |
@@ -101,6 +99,7 @@ class Api(ApiTemplate): | @@ -101,6 +99,7 @@ class Api(ApiTemplate): | ||
101 | raise e | 99 | raise e |
102 | return res | 100 | return res |
103 | 101 | ||
102 | + | ||
104 | api_doc = { | 103 | api_doc = { |
105 | "tags": ["切片服务接口"], | 104 | "tags": ["切片服务接口"], |
106 | "parameters": [ | 105 | "parameters": [ |
1 | +# coding=utf-8 | ||
2 | +#author: 4N | ||
3 | +#createtime: 2021/7/19 | ||
4 | +#email: nheweijun@sina.com | ||
5 | + | ||
6 | + | ||
7 | +from app.util.component.ApiTemplate import ApiTemplate | ||
8 | +from ..models import TileService,db,Service | ||
9 | +import configure | ||
10 | +from app.util.component.ModelVisitor import ModelVisitor | ||
11 | + | ||
12 | +from .util.ProjectFile import ProjectFile | ||
13 | + | ||
14 | +class Api(ApiTemplate): | ||
15 | + | ||
16 | + api_name = "切片服务reload" | ||
17 | + | ||
18 | + def process(self): | ||
19 | + res = {} | ||
20 | + try: | ||
21 | + tile_services = TileService.query.join(Service).filter(Service.type=="切片服务").all() | ||
22 | + res["data"] = {} | ||
23 | + res["data"]["count"] = len(tile_services) | ||
24 | + res["data"]["list"] = [] | ||
25 | + for ts in tile_services: | ||
26 | + project_file = ProjectFile.create(ModelVisitor.object_to_json(ts)) | ||
27 | + service:Service = Service.query.filter_by(guid=ts.service_guid).one_or_none() | ||
28 | + para = {"name":service.name,"title":service.title, | ||
29 | + "type":"tileserver","capabilities":1,"project":project_file} | ||
30 | + res["data"]["list"].append(para) | ||
31 | + res["result"] = True | ||
32 | + except Exception as e: | ||
33 | + raise e | ||
34 | + return res | ||
35 | + | ||
36 | + api_doc = { | ||
37 | + "tags": ["切片服务接口"], | ||
38 | + "parameters": [ | ||
39 | + ], | ||
40 | + "responses": { | ||
41 | + 200: { | ||
42 | + "schema": { | ||
43 | + "properties": { | ||
44 | + } | ||
45 | + } | ||
46 | + } | ||
47 | + } | ||
48 | + } |
1 | +# coding=utf-8 | ||
2 | +#author: 4N | ||
3 | +#createtime: 2021/12/6 | ||
4 | +#email: nheweijun@sina.com | ||
5 | + | ||
6 | + | ||
7 | +from app.modules.service.models import TileScheme | ||
8 | +from app.util.component.ModelVisitor import ModelVisitor | ||
9 | +import json | ||
10 | +import base64 | ||
11 | + | ||
12 | + | ||
13 | +class ProjectFile: | ||
14 | + | ||
15 | + @classmethod | ||
16 | + def create(cls,para): | ||
17 | + if para.get("tile_type").__eq__("WMTS"): | ||
18 | + | ||
19 | + if para.get("scheme"): | ||
20 | + tile_scheme = json.loads(para.get("scheme")) | ||
21 | + else: | ||
22 | + tile_scheme: TileScheme = TileScheme.query.filter_by(guid=para.get("scheme_guid")).one_or_none() | ||
23 | + if not tile_scheme: | ||
24 | + raise Exception("切片方案不存在!") | ||
25 | + tile_scheme = ModelVisitor.object_to_json(tile_scheme) | ||
26 | + | ||
27 | + project_xml_format = '''<?xml version="1.0"?> | ||
28 | + <dmap projectname="wmtstest" version="4.0"> | ||
29 | + <projectCrs> | ||
30 | + <spatialrefsys> | ||
31 | + <wkt>{wkt}</wkt> | ||
32 | + <proj4>{proj4}</proj4> | ||
33 | + <srid>{srid}</srid> | ||
34 | + <description/> | ||
35 | + <projectionacronym/> | ||
36 | + </spatialrefsys> | ||
37 | + </projectCrs> | ||
38 | + <projectlayers> | ||
39 | + <maplayer name="{name}" alias="{alias}" type="0"> | ||
40 | + <extent> | ||
41 | + <xmin>{xmin}</xmin> | ||
42 | + <ymin>{xmax}</ymin> | ||
43 | + <xmax>{xmax}</xmax> | ||
44 | + <ymax>{ymax}</ymax> | ||
45 | + </extent> | ||
46 | + <style>{layer_style}</style> | ||
47 | + <format>{layer_format}</format> | ||
48 | + <vendor>{vendor}</vendor> | ||
49 | + <datasource>{datasource}</datasource> | ||
50 | + <tileMatrixSets> | ||
51 | + <tileMatrixSet> | ||
52 | + <id>default</id> | ||
53 | + <crs>{crs}</crs> | ||
54 | + <tileCols>{cols}</tileCols> | ||
55 | + <tileRows>{rows}</tileRows> | ||
56 | + <dpi>{dpi}</dpi> | ||
57 | + <tileOrigin> | ||
58 | + <X>{x}</X> | ||
59 | + <Y>{y}</Y> | ||
60 | + </tileOrigin> | ||
61 | + <levels> | ||
62 | + {levels} | ||
63 | + </levels> | ||
64 | + </tileMatrixSet> | ||
65 | + </tileMatrixSets> | ||
66 | + </maplayer> | ||
67 | + </projectlayers> | ||
68 | + </dmap> | ||
69 | + ''' | ||
70 | + | ||
71 | + level_each = '''<level> | ||
72 | + <id>{lev}</id> | ||
73 | + <scaleDenominator>{scale}</scaleDenominator> | ||
74 | + <resolution>{resolution}</resolution> | ||
75 | + </level>''' | ||
76 | + | ||
77 | + levels = "" | ||
78 | + for level in json.loads(tile_scheme.get("levels")): | ||
79 | + levels = "{}{}".format(levels, level_each.format(lev=level["level"], | ||
80 | + scale=level["scale"], | ||
81 | + resolution=level["resolution"], | ||
82 | + )) | ||
83 | + | ||
84 | + layer_extent = para.get("layer_extent").split(",") | ||
85 | + | ||
86 | + project_xml = project_xml_format.format(wkt="", | ||
87 | + proj4="", | ||
88 | + srid=para.get("crs").split("::")[-1], | ||
89 | + name=para.get("layer_name"), | ||
90 | + alias=para.get("alias"), | ||
91 | + xmin=layer_extent[0], | ||
92 | + xmax=layer_extent[1], | ||
93 | + ymin=layer_extent[2], | ||
94 | + ymax=layer_extent[3], | ||
95 | + layer_style=para.get("layer_style"), | ||
96 | + layer_format=para.get("layer_format"), | ||
97 | + vendor=para.get("vendor"), | ||
98 | + datasource=para.get("datasource"), | ||
99 | + crs=para.get("crs"), | ||
100 | + cols=tile_scheme.get("cols"), | ||
101 | + rows=tile_scheme.get("rows"), | ||
102 | + dpi=tile_scheme.get("dpi"), | ||
103 | + x=tile_scheme.get("top_left").split(",")[0], | ||
104 | + y=tile_scheme.get("top_left").split(",")[1], | ||
105 | + levels=levels | ||
106 | + ) | ||
107 | + else: | ||
108 | + | ||
109 | + project_xml_format = '''<?xml version="1.0"?> | ||
110 | + <dmap projectname="tmstest" version="4.0"> | ||
111 | + <projectCrs> | ||
112 | + <spatialrefsys> | ||
113 | + <wkt>{wkt}</wkt> | ||
114 | + <proj4>{proj4}</proj4> | ||
115 | + <srid>{srid}</srid> | ||
116 | + <description/> | ||
117 | + <projectionacronym/> | ||
118 | + </spatialrefsys> | ||
119 | + </projectCrs> | ||
120 | + <projectlayers> | ||
121 | + <maplayer name="{name}" alias="{alias}" type="3"> | ||
122 | + <extent> | ||
123 | + <xmin>{xmin}</xmin> | ||
124 | + <ymin>{xmax}</ymin> | ||
125 | + <xmax>{xmax}</xmax> | ||
126 | + <ymax>{ymax}</ymax> | ||
127 | + </extent> | ||
128 | + <style>{layer_style}</style> | ||
129 | + <format>{layer_format}</format> | ||
130 | + <vendor>{vendor}</vendor> | ||
131 | + <datasource>{datasource}</datasource> | ||
132 | + </maplayer> | ||
133 | + </projectlayers> | ||
134 | + </dmap> | ||
135 | + | ||
136 | + ''' | ||
137 | + layer_extent = para.get("layer_extent").split(",") | ||
138 | + project_xml = project_xml_format.format(wkt="", | ||
139 | + proj4="", | ||
140 | + srid=para.get("crs").split("::")[-1], | ||
141 | + name=para.get("layer_name"), | ||
142 | + alias=para.get("alias"), | ||
143 | + xmin=layer_extent[0], | ||
144 | + xmax=layer_extent[1], | ||
145 | + ymin=layer_extent[2], | ||
146 | + ymax=layer_extent[3], | ||
147 | + layer_style=para.get("layer_style"), | ||
148 | + layer_format=para.get("layer_format"), | ||
149 | + vendor=para.get("vendor"), | ||
150 | + datasource=para.get("datasource"), | ||
151 | + ) | ||
152 | + return str(base64.b64encode(project_xml.encode('utf-8')), encoding="utf8") |
@@ -107,4 +107,10 @@ class PGUtil: | @@ -107,4 +107,10 @@ class PGUtil: | ||
107 | 107 | ||
108 | @classmethod | 108 | @classmethod |
109 | def check_database_privilege(cls,table_name,pri_type,user,session): | 109 | def check_database_privilege(cls,table_name,pri_type,user,session): |
110 | - pass | ||
110 | + pass | ||
111 | + | ||
112 | +if __name__ == '__main__': | ||
113 | + session:Session = PGUtil.get_db_session("postgresql://postgres:chinadci@172.26.60.100:5432/template1") | ||
114 | + result = session.execute("SELECT datname FROM pg_database;") | ||
115 | + for re in result: | ||
116 | + print(re) |
@@ -4,8 +4,8 @@ import logging | @@ -4,8 +4,8 @@ import logging | ||
4 | deploy_ip_host = "172.26.40.105:8840" | 4 | deploy_ip_host = "172.26.40.105:8840" |
5 | # 系统数据库 | 5 | # 系统数据库 |
6 | 6 | ||
7 | -# SQLALCHEMY_DATABASE_URI = "postgresql://postgres:chinadci@172.26.60.100:5432/dmap_manager_test" | ||
8 | -SQLALCHEMY_DATABASE_URI = "postgresql://postgres:postgres@localhost:5433/dmap_dms_test" | 7 | +SQLALCHEMY_DATABASE_URI = "postgresql://postgres:chinadci@172.26.60.100:5432/dmap_manager" |
8 | +# SQLALCHEMY_DATABASE_URI = "postgresql://postgres:postgres@localhost:5433/dmap_dms_test" | ||
9 | 9 | ||
10 | # 指定精华表所在位置(必须为空间库),设置为None则存放在各自的实体库中 | 10 | # 指定精华表所在位置(必须为空间库),设置为None则存放在各自的实体库中 |
11 | #VACUATE_DB_URI = None | 11 | #VACUATE_DB_URI = None |
@@ -356,12 +356,14 @@ LoadModule wsgi_module "/usr/lib64/httpd/modules/mod_wsgi-py37.cpython-37m-x86_6 | @@ -356,12 +356,14 @@ LoadModule wsgi_module "/usr/lib64/httpd/modules/mod_wsgi-py37.cpython-37m-x86_6 | ||
356 | "/var/gdal" | 356 | "/var/gdal" |
357 | 357 | ||
358 | dmapmanager processes=4 threads=16 display-name=%{GROUP} | 358 | dmapmanager processes=4 threads=16 display-name=%{GROUP} |
359 | + | ||
359 | dmapmanager | 360 | dmapmanager |
360 | #Authorization请求头顺利转发 | 361 | #Authorization请求头顺利转发 |
361 | On | 362 | On |
362 | %{GLOBAL} | 363 | %{GLOBAL} |
363 | 364 | ||
364 | / /usr/src/app/run.wsgi | 365 | / /usr/src/app/run.wsgi |
366 | + | ||
365 | <Directory /usr/> | 367 | <Directory /usr/> |
366 | Require all granted | 368 | Require all granted |
367 | </Directory> | 369 | </Directory> |
@@ -19,7 +19,7 @@ import time | @@ -19,7 +19,7 @@ import time | ||
19 | # table="fs900w_1" | 19 | # table="fs900w_1" |
20 | # sql ="SELECT geom FROM {} WHERE geom && 'BOX3D({})'::box3d limit 100000".format(table,bbox) | 20 | # sql ="SELECT geom FROM {} WHERE geom && 'BOX3D({})'::box3d limit 100000".format(table,bbox) |
21 | 21 | ||
22 | - | 22 | +import base64 |
23 | def query_thread(): | 23 | def query_thread(): |
24 | def get_db_session(db_url, autocommit=False) -> Session: | 24 | def get_db_session(db_url, autocommit=False) -> Session: |
25 | engine = create_engine(db_url, pool_size=100) | 25 | engine = create_engine(db_url, pool_size=100) |
@@ -53,6 +53,5 @@ def query_thread(): | @@ -53,6 +53,5 @@ def query_thread(): | ||
53 | ses.close() | 53 | ses.close() |
54 | # query_thread() | 54 | # query_thread() |
55 | if __name__ == '__main__': | 55 | if __name__ == '__main__': |
56 | - kk = [1,2,3,4,5,6,7,8,9,10,11] | ||
57 | - print(len(kk)) | ||
58 | - print(kk[10:20]) | ||
56 | + kk="PD94bWwgdmVyc2lvbj0iMS4wIj8+CiAgICAgICAgICAgIDxkbWFwIHByb2plY3RuYW1lPSJ3bXRzdGVzdCIgdmVyc2lvbj0iNC4wIj4KICAgICAgICAgICAgICA8cHJvamVjdENycz4KICAgICAgICAgICAgICAgIDxzcGF0aWFscmVmc3lzPgogICAgICAgICAgICAgICAgICA8d2t0Pjwvd2t0PgogICAgICAgICAgICAgICAgICA8cHJvajQ+PC9wcm9qND4KICAgICAgICAgICAgICAgICAgPHNyaWQ+NDQ5MDwvc3JpZD4KICAgICAgICAgICAgICAgICAgPGRlc2NyaXB0aW9uLz4KICAgICAgICAgICAgICAgICAgPHByb2plY3Rpb25hY3JvbnltLz4KICAgICAgICAgICAgICAgIDwvc3BhdGlhbHJlZnN5cz4KICAgICAgICAgICAgICA8L3Byb2plY3RDcnM+CiAgICAgICAgICAgICAgPHByb2plY3RsYXllcnM+CiAgICAgICAgICAgICAgICA8bWFwbGF5ZXIgbmFtZT0ibGF5ZXIiIGFsaWFzPSJOb25lIiB0eXBlPSIwIj4KICAgICAgICAgICAgICAgICAgPGV4dGVudD4KICAgICAgICAgICAgICAgICAgICA8eG1pbj4xMDcuNzg5ODE0OTQxODA2MTg8L3htaW4+CiAgICAgICAgICAgICAgICAgICAgPHltaW4+MTIwLjQzNTUzNjAzOTM1Njc1PC95bWluPgogICAgICAgICAgICAgICAgICAgIDx4bWF4PjEyMC40MzU1MzYwMzkzNTY3NTwveG1heD4KICAgICAgICAgICAgICAgICAgICA8eW1heD4yNS45OTk4Njg3NTc3MzcwMzM8L3ltYXg+CiAgICAgICAgICAgICAgICAgIDwvZXh0ZW50PgogICAgICAgICAgICAgICAgICA8c3R5bGU+ZGVmYXVsdDwvc3R5bGU+CiAgICAgICAgICAgICAgICAgIDxmb3JtYXQ+aW1hZ2UvcG5nPC9mb3JtYXQ+CiAgICAgICAgICAgICAgICAgIDx2ZW5kb3I+RVNSSV9WMTwvdmVuZG9yPgogICAgICAgICAgICAgICAgICA8ZGF0YXNvdXJjZT4vdXNyL2xvY2FsL2RtYXA0L2dkbWFwL19hbGxsYXllcnM8L2RhdGFzb3VyY2U+CiAgICAgICAgICAgICAgICAgIDx0aWxlTWF0cml4U2V0cz4KICAgICAgICAgICAgICAgICAgICA8dGlsZU1hdHJpeFNldD4KICAgICAgICAgICAgICAgICAgICAgIDxpZD5kZWZhdWx0PC9pZD4KICAgICAgICAgICAgICAgICAgICAgIDxjcnM+RVBTRzo6NDQ5MDwvY3JzPgogICAgICAgICAgICAgICAgICAgICAgPHRpbGVDb2xzPjI1NjwvdGlsZUNvbHM+CiAgICAgICAgICAgICAgICAgICAgICA8dGlsZVJvd3M+MjU2PC90aWxlUm93cz4KICAgICAgICAgICAgICAgICAgICAgIDxkcGk+OTY8L2RwaT4KICAgICAgICAgICAgICAgICAgICAgIDx0aWxlT3JpZ2luPgogICAgICAgICAgICAgICAgICAgICAgICA8WD40MDA8L1g+CiAgICAgICAgICAgICAgICAgICAgICAgIDxZPi00MDA8L1k+CiAgICAgICAgICAgICAgICAgICAgICA8L3RpbGVPcmlnaW4+CiAgICAgICAgICAgICAgICAgICAgICA8bGV2ZWxzPgogICAgICAgICAgICAgICAgICAgICAgICA8bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD4wPC9pZD4KICAgICAgICAgICAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+NTkwOTk1MTg2LjEyPC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4xLjQwNjI1MDAwMDAwNTk0ODg8L3Jlc29sdXRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGV2ZWw+PGxldmVsPgogICAgICAgICAgICAgICAgICAgICAgICA8aWQ+MTwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjI5NTQ5NzU5My4wNjwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC43MDMxMjUwMDAwMDI5NzQ0PC9yZXNvbHV0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8L2xldmVsPjxsZXZlbD4KICAgICAgICAgICAgICAgICAgICAgICAgPGlkPjI8L2lkPgogICAgICAgICAgICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4xNDc3NDg3OTYuNTM8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMzUxNTYyNTAwMDAxNDg3MjwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD4zPC9pZD4KICAgICAgICAgICAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+NzM4NzQzOTguMjY1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4wLjE3NTc4MTI1MDAwMDc0MzY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGV2ZWw+PGxldmVsPgogICAgICAgICAgICAgICAgICAgICAgICA8aWQ+NDwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjM2OTM3MTk5LjEzMjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDg3ODkwNjI1MDAwMzcxODwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD41PC9pZD4KICAgICAgICAgICAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+MTg0Njg1OTkuNTY2MjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDQzOTQ1MzEyNTAwMTg1OTwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD42PC9pZD4KICAgICAgICAgICAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+OTIzNDI5OS43ODMxMjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDIxOTcyNjU2MjUwMDkyOTU8L3Jlc29sdXRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGV2ZWw+PGxldmVsPgogICAgICAgICAgICAgICAgICAgICAgICA8aWQ+NzwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjQ2MTcxNDkuODkxNTYyNTwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMTA5ODYzMjgxMjUwNDY0NzU8L3Jlc29sdXRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGV2ZWw+PGxldmVsPgogICAgICAgICAgICAgICAgICAgICAgICA8aWQ+ODwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjIzMDg1NzQuOTQ1NzgxMjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDA1NDkzMTY0MDYyNTIzMjM3NTwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD45PC9pZD4KICAgICAgICAgICAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+MTE1NDI4Ny40NzI4OTA2MjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDAyNzQ2NTgyMDMxMjYxNjE4NzwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD4xMDwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjU3NzE0My43MzY0NDUzMTI1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4wLjAwMTM3MzI5MTAxNTYzMDgwOTQ8L3Jlc29sdXRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGV2ZWw+PGxldmVsPgogICAgICAgICAgICAgICAgICAgICAgICA8aWQ+MTE8L2lkPgogICAgICAgICAgICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4yODg1NzEuODY4MjIyNjU2MjU8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjAuMDAwNjg2NjQ1NTA3ODE1NDA0NzwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD4xMjwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjE0NDI4NS45MzQxMTEzMjgxMzwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICAgICAgICAgICAgPHJlc29sdXRpb24+MC4wMDAzNDMzMjI3NTM5MDc3MDIzNDwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD4xMzwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjcyMTQyLjk2NzA1NTY2NDA2PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4wLjAwMDE3MTY2MTM3Njk1Mzg1MTE3PC9yZXNvbHV0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8L2xldmVsPjxsZXZlbD4KICAgICAgICAgICAgICAgICAgICAgICAgPGlkPjE0PC9pZD4KICAgICAgICAgICAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+MzYwNzEuNDgzNTI3ODMyMDM8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjguNTgzMDY4ODQ3NjkyNTU5ZS0wNTwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD4xNTwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjE4MDM1Ljc0MTc2MzkxNjAxNjwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICAgICAgICAgICAgPHJlc29sdXRpb24+NC4yOTE1MzQ0MjM4NDYyNzllLTA1PC9yZXNvbHV0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8L2xldmVsPjxsZXZlbD4KICAgICAgICAgICAgICAgICAgICAgICAgPGlkPjE2PC9pZD4KICAgICAgICAgICAgICAgICAgICAgICAgPHNjYWxlRGVub21pbmF0b3I+OTAxNy44NzA4ODE5NTgwMDg8L3NjYWxlRGVub21pbmF0b3I+CiAgICAgICAgICAgICAgICAgICAgICAgIDxyZXNvbHV0aW9uPjIuMTQ1NzY3MjExOTIzMTM5NmUtMDU8L3Jlc29sdXRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGV2ZWw+PGxldmVsPgogICAgICAgICAgICAgICAgICAgICAgICA8aWQ+MTc8L2lkPgogICAgICAgICAgICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj40NTA4LjkzNTQ0MDk3OTAwNDwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICAgICAgICAgICAgPHJlc29sdXRpb24+MS4wNzI4ODM2MDU5NjE1Njk4ZS0wNTwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD4xODwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjIyNTQuNDY3NzIwNDg5NTAyPC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgICAgICAgICAgICA8cmVzb2x1dGlvbj41LjM2NDQxODAyOTgwNzg0OWUtMDY8L3Jlc29sdXRpb24+CiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGV2ZWw+PGxldmVsPgogICAgICAgICAgICAgICAgICAgICAgICA8aWQ+MTk8L2lkPgogICAgICAgICAgICAgICAgICAgICAgICA8c2NhbGVEZW5vbWluYXRvcj4xMTI3LjIzMzg2MDI0NDc1MTwvc2NhbGVEZW5vbWluYXRvcj4KICAgICAgICAgICAgICAgICAgICAgICAgPHJlc29sdXRpb24+Mi42ODIyMDkwMTQ5MDM5MjQ2ZS0wNjwvcmVzb2x1dGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbD48bGV2ZWw+CiAgICAgICAgICAgICAgICAgICAgICAgIDxpZD4yMDwvaWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDxzY2FsZURlbm9taW5hdG9yPjU2My42MTY5MzAxMjIzNzU1PC9zY2FsZURlbm9taW5hdG9yPgogICAgICAgICAgICAgICAgICAgICAgICA8cmVzb2x1dGlvbj4xLjM0MTEwNDUwNzQ1MTk2MjNlLTA2PC9yZXNvbHV0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICA8L2xldmVsPgogICAgICAgICAgICAgICAgICAgICAgPC9sZXZlbHM+CiAgICAgICAgICAgICAgICAgICAgPC90aWxlTWF0cml4U2V0PgogICAgICAgICAgICAgICAgICA8L3RpbGVNYXRyaXhTZXRzPgogICAgICAgICAgICAgICAgPC9tYXBsYXllcj4KICAgICAgICAgICAgICA8L3Byb2plY3RsYXllcnM+CiAgICAgICAgICAgIDwvZG1hcD4KICAgICAgICAgICAg" | ||
57 | + print('解码:' + str(base64.b64decode(kk), "utf-8")) |
请
注册
或
登录
后发表评论