1- // using System.ComponentModel.DataAnnotations;
2- // using System.Threading.Tasks;
3- // using Microsoft.AspNetCore.Http.Extensions;
4- // using Microsoft.AspNetCore.Mvc;
5- // using Microsoft.Extensions.Logging;
6- // using Orleans;
7- // using SkiaSharp;
8- // using ZMap.Source.CloudOptimizedGeoTIFF;
9- // using ZServer.Store;
10- //
11- // namespace ZServer.API.Controllers;
12- //
13- // [ApiController]
14- // [Microsoft.AspNetCore.Components.Route("[controller]")]
15- // public class XyzController(ILogger<XyzController> logger, IClusterClient clusterClient, ISourceStore sourceStore)
16- // : ControllerBase
17- // {
18- // [HttpGet("{layers}")]
19- // public async Task<IActionResult> GetAsync([FromRoute, Required, StringLength(100)] string layers,
20- // [FromQuery] int x, [FromQuery] int y, [FromQuery, StringLength(100)] string z,
21- // [StringLength(20)] string format = "image/png")
22- // {
23- // var displayUrl = Request.GetDisplayUrl();
24- // if (string.IsNullOrWhiteSpace(layers))
25- // {
26- // logger.LogError($"LAYERS should not be empty/null: {displayUrl}");
27- // return NotFound();
28- // }
29- //
30- // // var sourceList = layers.Split(',', StringSplitOptions.RemoveEmptyEntries);
31- // // foreach (var source in sourceList)
32- // // {
33- // //
34- // // }
35- // var source = await sourceStore.FindAsync(layers);
36- // if (source is COGGeoTiffSource cogSource)
37- // {
38- // var image = await cogSource.GetImageAsync(z, x, y);
39- //
40- // var skiaImage = SKImage.FromEncodedData(image);
41- // var imageFormat = GetImageFormat(format);
42- // await using var stream = skiaImage.Encode(imageFormat, 90).AsStream();
43- // return File(stream, "image/png");
44- // }
45- //
46- // return File([], "image/png");
47- // }
48- //
49- // private SKEncodedImageFormat GetImageFormat(string format)
50- // {
51- // return format switch
52- // {
53- // "image/png" => SKEncodedImageFormat.Png,
54- // "image/jpeg" => SKEncodedImageFormat.Jpeg,
55- // "image/webp" => SKEncodedImageFormat.Webp,
56- // "image/gif" => SKEncodedImageFormat.Gif,
57- // "image/bmp" => SKEncodedImageFormat.Bmp,
58- // _ => SKEncodedImageFormat.Png
59- // };
60- // }
61- // }
1+ using System . Collections . Generic ;
2+ using System . ComponentModel . DataAnnotations ;
3+ using System . Threading . Tasks ;
4+ using Microsoft . AspNetCore . Authorization ;
5+ using Microsoft . AspNetCore . Mvc ;
6+ using Microsoft . Extensions . Logging ;
7+ using Orleans ;
8+ using SkiaSharp ;
9+ using ZMap ;
10+ using ZMap . Infrastructure ;
11+ using ZServer . Interfaces . WMTS ;
12+
13+ namespace ZServer . API . Controllers ;
14+
15+ /// <summary>
16+ /// WMS 服务
17+ /// </summary>
18+ /// <param name="clusterClient"></param>
19+ /// <param name="logger"></param>
20+ [ ApiController ]
21+ [ Route ( "[controller]" ) ]
22+ [ Authorize ( Policy = "default" ) ]
23+ [ Microsoft . AspNetCore . Components . Route ( "[controller]" ) ]
24+ public class XyzController ( ILogger < XyzController > logger , IClusterClient clusterClient )
25+ : ControllerBase
26+ {
27+ /// <summary>
28+ /// 90% xyz 都是默认 3857
29+ /// </summary>
30+ /// <param name="layers"></param>
31+ /// <param name="x"></param>
32+ /// <param name="y"></param>
33+ /// <param name="z"></param>
34+ /// <param name="filter"></param>
35+ /// <param name="format"></param>
36+ /// <param name="tileMatrixSet"></param>
37+ /// <param name="style"></param>
38+ /// <param name="bordered"></param>
39+ [ HttpGet ( "{layers}" ) ]
40+ public async Task GetAsync ( [ FromRoute , Required , StringLength ( 100 ) ] string layers ,
41+ [ FromQuery ] int x , [ FromQuery ] int y , [ FromQuery , StringLength ( 100 ) ] string z ,
42+ [ FromQuery ( Name = "Z_FILTER" ) , StringLength ( 2048 ) ]
43+ string filter = null ,
44+ [ StringLength ( 20 ) ] string format = "image/png" , [ StringLength ( 12 ) ] string tileMatrixSet = "3857" ,
45+ [ StringLength ( 255 ) ] string style = null , bool bordered = false )
46+ {
47+ tileMatrixSet = $ "EPSG:{ tileMatrixSet } ";
48+ var tileMatrix = z ;
49+ var tileCol = x ;
50+ var tileRow = y ;
51+ var tuple = Utility . GetWmtsPath ( layers , filter , format , tileMatrixSet , tileMatrix , tileRow , tileCol , bordered ) ;
52+
53+ logger . LogDebug ( "[{TraceIdentifier}] Request wmts service {TileMatrix} {TileMatrixSet} {TileCol} {TileRow}" ,
54+ HttpContext . TraceIdentifier , tileMatrix , tileMatrixSet , tileCol , tileRow ) ;
55+
56+ #if ! DEBUG
57+ if ( System . IO . File . Exists ( tuple . FullPath ) )
58+ {
59+ if ( EnvironmentVariables . EnableSensitiveDataLogging )
60+ {
61+ var displayUrl =
62+ $ "[{ HttpContext . TraceIdentifier } ] LAYERS={ layers } &STYLES={ style } &FORMAT={ format } &TILEMATRIXSET={ tileMatrixSet } &TILEMATRIX={ tileMatrix } &TILEROW={ tileRow } &TILECOL={ tileCol } ";
63+ logger . LogInformation ( "{Service} [{TraceIdentifier}] {Url}, CACHED" , "XYZ" , HttpContext . TraceIdentifier ,
64+ displayUrl ) ;
65+ }
66+
67+ await using var stream = System . IO . File . OpenRead ( tuple . FullPath ) ;
68+ HttpContext . Response . ContentType = format ;
69+ HttpContext . Response . ContentLength = stream . Length ;
70+ await stream . CopyToAsync ( HttpContext . Response . Body , ( int ) stream . Length ) ;
71+ return ;
72+ }
73+ #endif
74+
75+ // 同一个 Grid 使用同一个对象进行管理, 保证缓存文件在同一个 Silo 目录下
76+ var grain = clusterClient . GetGrain < IWMTSGrain > ( tuple . IntervalPath ) ;
77+
78+ var result =
79+ await grain . GetTileAsync ( layers , style , format , tileMatrixSet , tileMatrix , tileRow , tileCol ,
80+ filter ,
81+ new Dictionary < string , object >
82+ {
83+ { Defaults . TraceIdentifier , HttpContext . TraceIdentifier } ,
84+ { "Bordered" , bordered }
85+ } ) ;
86+
87+ await HttpContext . WriteZServerResponseAsync ( result ) ;
88+ }
89+
90+ private SKEncodedImageFormat GetImageFormat ( string format )
91+ {
92+ return format switch
93+ {
94+ "image/png" => SKEncodedImageFormat . Png ,
95+ "image/jpeg" => SKEncodedImageFormat . Jpeg ,
96+ "image/webp" => SKEncodedImageFormat . Webp ,
97+ "image/gif" => SKEncodedImageFormat . Gif ,
98+ "image/bmp" => SKEncodedImageFormat . Bmp ,
99+ _ => SKEncodedImageFormat . Png
100+ } ;
101+ }
102+ }
0 commit comments