[mapguide-users] EXAMPLE: Serving MapTiles directly
Kenneth Skovhede, GEOGRAF A/S
ks at geograf.dk
Thu Feb 25 03:09:47 EST 2010
Wow, thanks.
Would you mind adding it to the CodeSamples?
For the IIS on XP problem, try this:
http://briancaos.wordpress.com/tag/adsutil/
PS: When you have using(), there is no need to close the stream explicitly.
Regards, Kenneth Skovhede, GEOGRAF A/S
On 24-02-2010 17:00, Pietro Ianniello wrote:
> Dear list,
> here is a simple ASP.NET <http://ASP.NET> ashx to server MapGuide
> Tiles Directly.
>
> It' different from the one found on
> "http://trac.osgeo.org/mapguide/wiki/CodeSamples/Tiles/ServingTilesViaHttp"
> because it doesn't require any web server configuration.
> The only point is to use my ashx as a proxy to MapGuide.
> Testing would be nice. If it's all OK, and someone wants to post it on
> wiki... or translate in PHP...
> BUT don't test it with a non server OS. For example in WindowsXP I get
> lot of empty tiles. This is not the case with Windows Server 2003.
> REMINDER FOR ME: don't loose time! Test on real server OSs!
> NOTE: *call somewhere
> "MapGuideApi.MgInitializeWebTier(MgMapHelper.WebconfigIniPhysicalPath);"
> before using this handler!*
> [*App_Start is a good choise*]
>
>
> Code:
>
> <%@ WebHandler Language="C#" Class="GetMGTiles" %>
> //#define LOG_WITH_LOG4NET
> using System;
> using System.Web;
>
> using System.Text;
> using System.Net;
> using System.Collections.Specialized;
> using MapGuideHelper;
> using OSGeo.MapGuide;
> using System.IO;
>
> //This is different from
> [http://trac.osgeo.org/mapguide/wiki/CodeSamples/Tiles/ServingTilesViaHttp
> ]
> //where the web server must be configured.
> //Here you use GetMGTiles.ashx as OpenLayers mapguide tiled layer
> address [not HttpTile!].
> //NOTE: if you try this with a non server OS [such as WindowsXP] you
> will certainly get missed tiles
> public class GetMGTiles : IHttpHandler
> {
> #region Compile Time Configuration
>
> private readonly int BUFF_SIZE = 20480;//4096
>
> #endregion
>
> #region Properties to be configured [if needed] on application start
>
> private static string _tileDirectory =
> "C:/OSGeo/MapGuide/Server/Repositories/TileCache/";
> public static string TileDirectory
> {
> get { return _tileDirectory; }
> set { _tileDirectory = value; }
> }
>
> private static string _imageFileFormat = ".png"; //depends on
> "serverconfig.ini"
> private static string _contentType = "image/png"; //depends on
> "serverconfig.ini"
> public static string ImageFileFormat
> {
> get { return _imageFileFormat; }
> set
> {
> _contentType = String.Concat("image/", value);
> _imageFileFormat = String.Concat(".", value);
> }
> }
>
> private static double _tileRowsPerFolder = 30.0; //depends on
> "serverconfig.ini"
> private static int _tileRowsPerFolderInt = 30; //depends on
> "serverconfig.ini"
> public static int TileRowsPerFolder
> {
> get { return _tileRowsPerFolderInt; }
> set { _tileRowsPerFolder = _tileRowsPerFolderInt = value; }
> }
> private static double _tileColumnsPerFolder = 30.0; //depends on
> "serverconfig.ini"
> private static int _tileColumnsPerFolderInt = 30; //depends on
> "serverconfig.ini"
> public static int TileColumnsPerFolder
> {
> get { return _tileColumnsPerFolderInt; }
> set { _tileColumnsPerFolder = _tileColumnsPerFolderInt = value; }
> }
>
> #endregion
>
> #region input request params
>
> int _tileRow, _tileCol, _scaleIndex;
> string _baseLayerGroupname;
> string _mapDefinition;
>
> #endregion
>
> protected void ServeMgTile(HttpResponse response)
> {
> MgUserInformation userInfo = null;
> MgSiteConnection siteConnection = null;
> MgTileService tileService = null;
> MgResourceIdentifier resIdent = null;
> MgByteReader mgReader = null;
> try
> {
>
> ///////MapGuideApi.MgInitializeWebTier(MgMapHelper.WebconfigIniPhysicalPath);
> userInfo = new MgUserInformation("Anonymous", "");
> siteConnection = new MgSiteConnection();
> siteConnection.Open(userInfo);
>
> tileService =
> siteConnection.CreateService(MgServiceType.TileService) as MgTileService;
> resIdent = new MgResourceIdentifier(_mapDefinition);
> mgReader = tileService.GetTile(resIdent,
> _baseLayerGroupname, _tileCol, _tileRow, _scaleIndex);
>
>
> //--------------------------------------------------------------
> //Debugging helper:
> // context.Response.Cache.SetNoStore();
> // context.Response.AppendHeader("Pragma", "no-cache");
>
> //--------------------------------------------------------------
>
> int readBytes;
> byte[] buffer = new byte[BUFF_SIZE];
> while ((readBytes = mgReader.Read(buffer, BUFF_SIZE)) > 0)
> {
> response.OutputStream.Write(buffer, 0, readBytes);
> }
> }
> finally
> {
> if (null != mgReader) mgReader.Dispose();
> if (null != resIdent) resIdent.Dispose();
> if (null != tileService) tileService.Dispose();
> if (null != siteConnection) siteConnection.Dispose();
> if (null != userInfo) userInfo.Dispose();
> }
> }
>
> protected void StreamFile(string filePath, HttpResponse response)
> {
> //response.AddHeader("content-disposition",
> String.Concat("attachment; filename=",Path.GetFileName(filePath)));
> using (FileStream fileStream = new FileStream(filePath,
> FileMode.Open, FileAccess.Read, FileShare.Read))
> {
> long fileSize = fileStream.Length;
> #if false
> //all at once:
> byte[] buffer = new byte[(int)fileSize];
> fileStream.Read(buffer, 0, (int)fileStream.Length);
> fileStream.Close();
> response.BinaryWrite(buffer);
> #else
> int readBytes;
> byte[] buffer = new byte[BUFF_SIZE];
> while ((readBytes = fileStream.Read(buffer, 0, BUFF_SIZE))
> > 0)
> {
> response.OutputStream.Write(buffer, 0, readBytes);
> }
> fileStream.Close();
> #endif
> }
> }
>
> public void ProcessRequest(HttpContext context)
> {
> try
> {
>
> //---------------------------------------------------------------------------------------------------------------------
> //Startup
>
> //---------------------------------------------------------------------------------------------------------------------
> //It's always GET, but this costs nothing:
> NameValueCollection nvInput = context.Request.HttpMethod
> == "POST" ?
>
> context.Request.Form : nvInput = context.Request.QueryString;
> #if false
> //string requestedUrl = context.Request.Path.ToLower();
> if (nvInput == null) //it's never null
> {
> context.Response.Clear();
> context.Response.ContentType = "text/plain";
> context.Response.Write("Hello World");
> return;
> }
> if (nvInput.Count == 0)//don't mind if is 0 => we will
> just get null strings when trying to read them
> {
> context.Response.Clear();
> context.Response.ContentType = "text/plain";
> context.Response.Write("Hello World");
> return;
> }
> #endif
>
> //---------------------------------------------------------------------------------------------------------------------
>
>
> //---------------------------------------------------------------------------------------------------------------------
> //Input params reading
>
> //---------------------------------------------------------------------------------------------------------------------
> _mapDefinition =
> HttpUtility.UrlDecode(nvInput["mapdefinition"]);
> if (String.IsNullOrEmpty(_mapDefinition))
> {
> context.Response.StatusCode =
> (int)HttpStatusCode.BadRequest;
> return;
> }
> if (nvInput["operation"].ToUpper() != "GETTILEIMAGE")
> {
> context.Response.StatusCode =
> (int)HttpStatusCode.BadRequest;
> return;
> }
> //---------------------------------
> //we don't read nvInput["version"]
> //---------------------------------
> _baseLayerGroupname =
> HttpUtility.UrlDecode(nvInput["basemaplayergroupname"]);
> if (String.IsNullOrEmpty(_baseLayerGroupname))
> {
> context.Response.StatusCode =
> (int)HttpStatusCode.BadRequest;
> return;
> }
> if (!Int32.TryParse(nvInput["tilecol"], out _tileCol))
> {
> context.Response.StatusCode =
> (int)HttpStatusCode.BadRequest;
> return;
> }
> if (!Int32.TryParse(nvInput["tilerow"], out _tileRow))
> {
> context.Response.StatusCode =
> (int)HttpStatusCode.BadRequest;
> return;
> }
> if (!Int32.TryParse(nvInput["scaleindex"], out _scaleIndex))
> {
> context.Response.StatusCode =
> (int)HttpStatusCode.BadRequest;
> return;
> }
>
>
> //---------------------------------------------------------------------------------------------------------------------
> //Tile file name
>
> //---------------------------------------------------------------------------------------------------------------------
> //The tiles base dir, if for example we want
> //
> "Library://Samples/Sheboygan/MapsTiled/Sheboygan.MapDefinition"
> // , is
> // "Samples_Sheboygan_MapsTiled_Sheboygan/"
> string mapDefDir = _mapDefinition.Replace("Library://",
> "").Replace("/", "_").Replace(".MapDefinition", "/");
>
>
> //---------------------------------
> //Taken from Openlayers:
> int tileRowGroup = (int)(Math.Floor(Math.Abs(_tileRow /
> _tileRowsPerFolder))) * TileRowsPerFolder;
> int tileColGroup = (int)(Math.Floor(Math.Abs(_tileCol /
> _tileColumnsPerFolder))) * TileColumnsPerFolder;
> int imgPartA = _tileRow % TileRowsPerFolder;
> int imgPartB = _tileCol % TileColumnsPerFolder;
> //---------------------------------
> StringBuilder sb = new StringBuilder(256);
> sb.Append(_tileDirectory);
> sb.Append(mapDefDir);
> sb.Append("S");
> sb.Append(this._scaleIndex);
> sb.Append("/");
> sb.Append(this._baseLayerGroupname);
> sb.Append("/R");
> sb.Append(tileRowGroup);
> sb.Append("/C");
> sb.Append(tileColGroup);
> sb.Append("/");
> sb.Append(imgPartA);
> sb.Append("_");
> sb.Append(imgPartB);
> sb.Append(_imageFileFormat);
>
> //---------------------------------------------------------------------------------------------------------------------
>
>
> //---------------------------------------------------------------------------------------------------------------------
> //We give file if possible, let mapGuide build the tile
> otherwise
>
> //---------------------------------------------------------------------------------------------------------------------
> context.Response.ContentType = _contentType;
> string file = sb.ToString();
> if (System.IO.File.Exists(file))
> {
> try
> {
> #if false
> context.Response.WriteFile(file);
> #else
> StreamFile(file, context.Response);
> #endif
> }
> catch (System.IO.IOException ex)
> {
> //FileExists is not enough:
> //MapGuide could possibly be writing the file
> while we where trying to get access!!!!
> #if LOG_WITH_LOG4NET
> log4net.ILog logger =
> log4net.LogManager.GetLogger("exceptions");
> logger.Error("GetMGTiles.ashx::ProcessRequest -
> Tried StreamFile [System.IO.IOException] - serve file via MapGuide", ex);
> #endif
> ServeMgTile(context.Response);
> }
>
> context.Response.Flush();
> context.Response.Close();
> }
> else
> {
> context.Response.ContentType = _contentType;
> ServeMgTile(context.Response);
> context.Response.Flush();
> context.Response.Close();
> }
> }
> catch (ArgumentNullException ex)
> {
> log4net.ILog logger =
> log4net.LogManager.GetLogger("exceptions");
> logger.Error("GetMGTiles.ashx::ProcessRequest
> [ArgumentNullException]", ex);
>
> context.Response.StatusCode = (int)HttpStatusCode.NotFound;
> System.Diagnostics.Trace.WriteLine(ex.ToString());
> }
> catch (System.Security.SecurityException ex)
> {
> #if LOG_WITH_LOG4NET
> log4net.ILog logger =
> log4net.LogManager.GetLogger("exceptions");
> logger.Error("GetMGTiles.ashx::ProcessRequest
> [SecurityException]", ex);
> #endif
> context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
> System.Diagnostics.Trace.WriteLine(ex.ToString());
> }
> catch (UriFormatException ex)
> {
> #if LOG_WITH_LOG4NET
> log4net.ILog logger =
> log4net.LogManager.GetLogger("exceptions");
> logger.Error("GetMGTiles.ashx::ProcessRequest
> [UriFormatException]", ex);
> #endif
> context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
> System.Diagnostics.Trace.WriteLine(ex.ToString());
> }
> catch (TimeoutException ex)
> {
> #if LOG_WITH_LOG4NET
> log4net.ILog logger =
> log4net.LogManager.GetLogger("exceptions");
> logger.Error("GetMGTiles.ashx::ProcessRequest
> [TimeoutException]", ex);
> #endif
> context.Response.StatusCode =
> (int)HttpStatusCode.RequestTimeout;
> System.Diagnostics.Trace.WriteLine(ex.ToString());
> }
> catch (Exception ex)
> {
> #if LOG_WITH_LOG4NET
> log4net.ILog logger =
> log4net.LogManager.GetLogger("exceptions");
> logger.Error("GetMGTiles.ashx::ProcessRequest
> [Exception]", ex);
> #endif
> context.Response.StatusCode =
> (int)HttpStatusCode.InternalServerError;
> System.Diagnostics.Trace.WriteLine(ex.ToString());
> }
> }
>
> public bool IsReusable
> {
> get
> {
> return false;
> }
> }
>
> }
>
> ------------
> Test page [slightly modified from the wiki]
> Assumes GetMGTiles.ashx is accessible in
> http://localhost/ash/GetMGTiles.ashx
> -----------
>
> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
> <html>
> <head>
> <title>Mapguide Http Tile Cache Demo</title>
>
> <script type="text/javascript"
> src="http://www.openlayers.org/api/OpenLayers.js"></script>
>
> </head>
> <body onload="initTiled()">
>
> <script type="text/javascript">
> var windowSize = 550; //200;//
> var extent;
>
> var addrs = "http://localhost/";
> //var addrs = "http://192.168.1.247/";
>
> var mg_url = addrs +
> "mapguide/mapagent/mapagent.fcgi?USERNAME=Anonymous&";
> var http_url = addrs + "sheboyganTiles";
> var my_proxy_url = addrs + "ash/GetMGTiles.ashx";
> var mg_map, http_or_tileproxy_map;
> var eventsLog = "";
> var c = 0;
> //var bUseHttpUrl = false; //http_url || my_proxy_url
>
> function initTiled() {
>
> document.getElementById('map_mg').style.width = windowSize;
> document.getElementById('map_http').style.width = windowSize;
>
> document.getElementById('map_mg').style.height = windowSize;
> document.getElementById('map_http').style.height = windowSize;
>
> OpenLayers.DOTS_PER_INCH = 96;
>
> //extent = new
> OpenLayers.Bounds(-87.865114442365922,43.665065564837931,-87.595394059497067,43.823852564430069);
>
> var extent = new OpenLayers.Bounds(-87.764986990963,
> 43.691398128788, -87.6955215109, 43.79752000048);
> var tempScales = [1000, 1930.6977300000001,
> 3727.5937199999998, 7196.8567300000004, 13894.95494, 26826.95795,
> 51794.746789999997, 100000];
>
> var mapOptions = {
> maxExtent: extent,
> restrictedExtent: extent,
> scales: tempScales
> };
>
> var params = {
> mapdefinition:
> 'Library://Samples/Sheboygan/MapsTiled/Sheboygan.MapDefinition',
> basemaplayergroupname: "Base Layer Group"
> }
>
> mg_map = new OpenLayers.Map('map_mg', mapOptions);
> http_or_tileproxy_map = new OpenLayers.Map('map_http',
> mapOptions);
>
> var mgOptions = {
> singleTile: false,
> useHttpTile: false,
> buffer: 1
> }
>
> /*var httpOptions = {
> singleTile: false,
> useHttpTile: true,
> buffer: 1
> }*/
>
> var myProxyOptions = {
> singleTile: false,
> useHttpTile: false,
> buffer: 1
> }
>
> mg_layer = new OpenLayers.Layer.MapGuide("MapGuide OS
> tiled layer", mg_url, params, mgOptions);
> //if (bUseHttpUrl) http_layer = new
> OpenLayers.Layer.MapGuide("MapGuide OS tiled layer", http_url, params,
> httpOptions);
> //else
> http_layer = new OpenLayers.Layer.MapGuide("MG OS proxy -
> tiled layer", my_proxy_url, params, myProxyOptions);
>
> mg_map.addLayer(mg_layer);
>
> mg_map.addControl(new OpenLayers.Control.MousePosition());
> http_or_tileproxy_map.addControl(new
> OpenLayers.Control.MousePosition());
>
> http_or_tileproxy_map.addLayer(http_layer);
>
> mg_map.setCenter(extent.getCenterLonLat());
> http_or_tileproxy_map.setCenter(extent.getCenterLonLat());
>
> mg_map.events.register("zoomend", mg_map, setZoomHttp);
> //http_or_tileproxy_map.events.register("zoomend",
> http_or_tileproxy_map, setZoomMg);
>
> mg_map.events.register("moveend", mg_map, moveHttp);
> //http_or_tileproxy_map.events.register("moveend",
> http_or_tileproxy_map, moveMg);
>
> }
>
> function moveHttp() {
> if (mg_map.getCenter() != http_or_tileproxy_map.getCenter())
> http_or_tileproxy_map.setCenter(mg_map.getCenter());
> }
>
> function moveMg() {
> if (mg_map.getCenter() != http_or_tileproxy_map.getCenter())
> mg_map.setCenter(http_or_tileproxy_map.getCenter());
> }
>
>
>
> function setZoomMg() {
> if (mg_map.getZoom() != http_or_tileproxy_map.getZoom())
> mg_map.zoomTo(http_or_tileproxy_map.getZoom());
> }
> function setZoomHttp() {
> if (mg_map.getZoom() != http_or_tileproxy_map.getZoom())
> http_or_tileproxy_map.zoomTo(mg_map.getZoom());
>
> }
>
> </script>
>
> <div style="float: left">
> <h1>Served by Mapguide</h1>
> <div id="map_mg" style="border: medium inset Maroon; float: left;
> background-color: #F5DEB3;">
> </div>
> <br />This cannot be proxied, it lacks cache headers
> </div>
> <div style="float: left">
> <h1>Served by Http</h1>
> <div id="map_http" style="border: medium inset Maroon; float: left;
> background-color: #F5DEB3;">
> </div>
> <br />This is can be proxied by proxy servers
> </div>
> </body>
> </html>
>
>
>
>
> ------------
> [OFFTOPIC] A suggestion about MapGuide Installer -
>
> it would be nice that besides the installer, there was a zipped
> archive with the installed files, to give the possibility of manually
> installing MapGuide without running an installer. This could be
> clearly set to UNSUPPORTED, and that no help would be given in the
> list to who desires to use the zipped archive.
>
> This is because, in my opinion, one cannot understand the system, if
> not by using a manual install. It's the path I followed when I for the
> first time used MapGuide.
>
> To provide such a thing is very simple: install in C:\OsGeo, zip
> folder and publish in "http://mapguide.osgeo.org/download". Only for
> windows, linux always needs compilation because of different shared
> objects between distributions.
>
> At this point one can extract the zip wherever she wants, change ini
> files, set virtual directories, enable PHP, change folder permissions,
> and the game is done!
> ------------
>
> Pietro Ianniello
>
>
> _______________________________________________
> mapguide-users mailing list
> mapguide-users at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/mapguide-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/mapguide-users/attachments/20100225/58d5be3e/attachment.html
More information about the mapguide-users
mailing list