By default, QGIS Server only caches WMS GetCapabilities document in memory. With WMTS implementation, it is necessary to have a way to cache tiles. But the cache manager has not been developed to only cache tiles.
The cache manager plugin, can be used to cache:
Here is a python cache manager class, which do not verifying if the QGIS project has changed:
class PyServerCache(QgsServerCacheFilter):
""" Used to have cache control """
def __init__(self, server_iface):
super(QgsServerCacheFilter, self).__init__(server_iface)
self._cache_dir = os.path.join(tempfile.gettempdir(), "qgs_server_cache")
if not os.path.exists(self._cache_dir):
os.mkdir(self._cache_dir)
self._tile_cache_dir = os.path.join(self._cache_dir, 'tiles')
if not os.path.exists(self._tile_cache_dir):
os.mkdir(self._tile_cache_dir)
def getCachedDocument(self, project, request, key):
m = hashlib.md5()
paramMap = request.parameters()
urlParam = "&".join(["%s=%s" % (k, paramMap[k]) for k in paramMap.keys()])
m.update(urlParam.encode('utf8'))
if not os.path.exists(os.path.join(self._cache_dir, m.hexdigest() + ".xml")):
return QByteArray()
doc = QDomDocument(m.hexdigest() + ".xml")
with open(os.path.join(self._cache_dir, m.hexdigest() + ".xml"), "r") as f:
statusOK, errorStr, errorLine, errorColumn = doc.setContent(f.read(), True)
if not statusOK:
print("Could not read or find the contents document. Error at line %d, column %d:\n%s" % (errorLine, errorColumn, errorStr))
return QByteArray()
return doc.toByteArray()
def setCachedDocument(self, doc, project, request, key):
if not doc:
print("Could not cache None document")
return False
m = hashlib.md5()
paramMap = request.parameters()
urlParam = "&".join(["%s=%s" % (k, paramMap[k]) for k in paramMap.keys()])
m.update(urlParam.encode('utf8'))
with open(os.path.join(self._cache_dir, m.hexdigest() + ".xml"), "w") as f:
f.write(doc.toString())
return os.path.exists(os.path.join(self._cache_dir, m.hexdigest() + ".xml"))
def deleteCachedDocument(self, project, request, key):
m = hashlib.md5()
paramMap = request.parameters()
urlParam = "&".join(["%s=%s" % (k, paramMap[k]) for k in paramMap.keys()])
m.update(urlParam.encode('utf8'))
if os.path.exists(os.path.join(self._cache_dir, m.hexdigest() + ".xml")):
os.remove(os.path.join(self._cache_dir, m.hexdigest() + ".xml"))
return not os.path.exists(os.path.join(self._cache_dir, m.hexdigest() + ".xml"))
def deleteCachedDocuments(self, project):
filelist = [f for f in os.listdir(self._cache_dir) if f.endswith(".xml")]
for f in filelist:
os.remove(os.path.join(self._cache_dir, f))
filelist = [f for f in os.listdir(self._cache_dir) if f.endswith(".xml")]
return len(filelist) == 0
def getCachedImage(self, project, request, key):
m = hashlib.md5()
paramMap = request.parameters()
urlParam = "&".join(["%s=%s" % (k, paramMap[k]) for k in paramMap.keys()])
m.update(urlParam.encode('utf8'))
if not os.path.exists(os.path.join(self._tile_cache_dir, m.hexdigest() + ".png")):
return QByteArray()
img = QImage(m.hexdigest() + ".png")
with open(os.path.join(self._tile_cache_dir, m.hexdigest() + ".png"), "rb") as f:
statusOK = img.loadFromData(f.read())
if not statusOK:
print("Could not read or find the contents document. Error at line %d, column %d:\n%s" % (errorLine, errorColumn, errorStr))
return QByteArray()
ba = QByteArray()
buff = QBuffer(ba)
buff.open(QIODevice.WriteOnly)
img.save(buff, 'PNG')
return ba
def setCachedImage(self, img, project, request, key):
m = hashlib.md5()
paramMap = request.parameters()
urlParam = "&".join(["%s=%s" % (k, paramMap[k]) for k in paramMap.keys()])
m.update(urlParam.encode('utf8'))
with open(os.path.join(self._tile_cache_dir, m.hexdigest() + ".png"), "wb") as f:
f.write(img)
return os.path.exists(os.path.join(self._tile_cache_dir, m.hexdigest() + ".png"))
def deleteCachedImage(self, project, request, key):
m = hashlib.md5()
paramMap = request.parameters()
urlParam = "&".join(["%s=%s" % (k, paramMap[k]) for k in paramMap.keys()])
m.update(urlParam.encode('utf8'))
if os.path.exists(os.path.join(self._tile_cache_dir, m.hexdigest() + ".png")):
os.remove(os.path.join(self._tile_cache_dir, m.hexdigest() + ".png"))
return not os.path.exists(os.path.join(self._tile_cache_dir, m.hexdigest() + ".png"))
def deleteCachedImages(self, project):
filelist = [f for f in os.listdir(self._tile_cache_dir) if f.endswith(".png")]
for f in filelist:
os.remove(os.path.join(self._tile_cache_dir, f))
filelist = [f for f in os.listdir(self._tile_cache_dir) if f.endswith(".png")]
return len(filelist) == 0
And the way to add it to the QGIS Server cache manager.
servercache = PyServerCache(server_iface)
server_iface.registerServerCache(servercache, 100)