如何在JavaScript中为Google Maps API的getTileUrl请求添加基础身份验证
方案1:优化现有代理服务解决加载慢问题
你当前代理加载慢的核心原因是ASPX页面本身有额外的页面生命周期开销、使用同步阻塞的WebClient请求、未复用HTTP连接,导致瓦片请求串行执行,优化步骤如下:
- 改用轻量的一般处理程序(
.ashx)代替ASPX页面,去掉不必要的页面生命周期开销 - 用单例
HttpClient复用HTTP连接,避免每次请求新建连接的握手开销 - 采用异步处理逻辑,支持多个瓦片请求并行执行
- 客户端和服务端都添加瓦片缓存,避免重复请求相同瓦片
优化后的代理代码(Charts.ashx)
using System; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Web; public class ChartsHandler : IHttpHandler, IRequiresSessionState { // 全局复用HttpClient,避免重复建立TCP连接 private static readonly HttpClient _httpClient = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }); public bool IsReusable => true; public async void ProcessRequest(HttpContext context) { context.Response.ContentType = "image/png"; context.Response.Cache.SetCacheability(HttpCacheability.Public); context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(30)); // 缓存30分钟,可按需调整 string parameters = context.Request.QueryString["p"]; string chartAuth = context.Session["chartAuth"]?.ToString(); if (string.IsNullOrEmpty(chartAuth) || string.IsNullOrEmpty(parameters)) { context.Response.StatusCode = 400; context.Response.End(); return; } string url = parameters.Replace("¬", "&"); using (var request = new HttpRequestMessage(HttpMethod.Get, url)) { request.Headers.Authorization = new AuthenticationHeaderValue("Basic", chartAuth); using (var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted)) { response.EnsureSuccessStatusCode(); using (var stream = await response.Content.ReadAsStreamAsync()) { await stream.CopyToAsync(context.Response.OutputStream); await context.Response.FlushAsync(); } } } } }
前端代码不需要改动,只需要把请求地址从Charts.aspx改成Charts.ashx即可,优化后瓦片可以并行加载,耗时会大幅降低。
方案2:无需代理,直接自定义瓦片请求
Google Maps API的ImageMapType支持自定义getTile方法,完全控制瓦片请求逻辑,直接携带身份验证头,不需要中转代理,是最优解决方案:
chartMapLayer = new google.maps.ImageMapType({ getTile: function(coord, zoom, ownerDocument) { const tile = ownerDocument.createElement('img'); const tileCoords = xyzToBounds(coord.x, coord.y, zoom).join(","); const url = ChartURL + '/?' + 'SERVICE=WMS' + '&<params go here.....>' + '&BBOX=' + tileCoords; // 用fetch请求携带Basic Auth头 fetch(url, { headers: { 'Authorization': 'Basic ' + 你的Base64编码的账号密码 } }).then(response => response.blob()) .then(blob => { tile.src = URL.createObjectURL(blob); }).catch(err => { // 加载失败的兜底逻辑 tile.src = '备用占位图地址'; }); tile.width = 256; tile.height = 256; return tile; }, maxZoom: 17, minZoom: 0, name: "CHARTWORLD", isPng: true, tileSize: new google.maps.Size(256, 256) });
*注意:如果瓦片服务存在跨域问题,需要服务端配置CORS允许你的域名请求,否则fetch请求会被浏览器拦截。无法配置CORS的场景优先使用优化后的代理方案。
内容的提问来源于stack exchange,提问作者Simon Rathbone
相关产品推荐
相关产品推荐

