Parcourir la source

GPX download endpoint

Lukas Angerer il y a 3 ans
Parent
commit
85afc6aabc

+ 7 - 0
src/RunnersMeet.Server/Controllers/TracksController.cs

@@ -72,4 +72,11 @@ public class TracksController : ControllerBase
 
 		return Ok();
 	}
+
+	[HttpGet("download/{hash}")]
+	public ActionResult DownloadGpx(string hash)
+	{
+		var track = _queryFactory.TrackQuery().GetByFileHash(hash);
+		return _fileStorage.FileDownload(track);
+	}
 }

+ 1 - 0
src/RunnersMeet.Server/Persistence/Database.cs

@@ -15,5 +15,6 @@ public class Database : IDatabase
 
 		Tracks = _db.GetCollection<Track>("tracks");
 		Tracks.EnsureIndex(t => t.Owner);
+		Tracks.EnsureIndex(t => t.FileHash);
 	}
 }

+ 11 - 1
src/RunnersMeet.Server/Persistence/FileName.cs

@@ -29,6 +29,16 @@ public class FileName
 
 	public static FileName FromTrack(Track track)
 	{
-		return new FileName(track.FileHash, $"{track.DisplayName}.gpx");
+		return new FileName(track.FileHash, $"{SafeFileName(track.DisplayName)}.gpx");
+	}
+
+	private static string SafeFileName(string name)
+	{
+		foreach (var c in Path.GetInvalidFileNameChars())
+		{
+			name = name.Replace(c, '.');
+		}
+
+		return name;
 	}
 }

+ 14 - 0
src/RunnersMeet.Server/Persistence/FileStorage.cs

@@ -1,3 +1,6 @@
+using Microsoft.AspNetCore.Mvc;
+using RunnersMeet.Server.Domain;
+
 namespace RunnersMeet.Server.Persistence;
 
 public class FileStorage : IFileStorage
@@ -25,6 +28,17 @@ public class FileStorage : IFileStorage
 		return File.OpenRead(path);
 	}
 
+	public FileStreamResult FileDownload(Track track)
+	{
+		var fileName = FileName.FromTrack(track);
+		var path = Path.Combine(_persistenceOptions.FileStorageRootPath, fileName.GetPath());
+		var fileStream = File.OpenRead(path);
+		return new FileStreamResult(fileStream, "application/gpx+xml")
+		{
+			FileDownloadName = fileName.DisplayName
+		};
+	}
+
 	private FileStream CreateFile(FileName name)
 	{
 		var path = Path.Combine(_persistenceOptions.FileStorageRootPath, name.GetPath());

+ 4 - 0
src/RunnersMeet.Server/Persistence/IFileStorage.cs

@@ -1,3 +1,6 @@
+using Microsoft.AspNetCore.Mvc;
+using RunnersMeet.Server.Domain;
+
 namespace RunnersMeet.Server.Persistence;
 
 public interface IFileStorage
@@ -5,4 +8,5 @@ public interface IFileStorage
 	public Task<FileName> UploadFileAsync(IFormFile file, CancellationToken cancellationToken = default);
 	public Stream OpenFileRead(FileName name);
 	public void DeleteFile(FileName name);
+	public FileStreamResult FileDownload(Track track);
 }

+ 5 - 0
src/RunnersMeet.Server/Persistence/TrackQuery.cs

@@ -16,4 +16,9 @@ public class TrackQuery
 	{
 		return _database.Tracks.FindById(trackId);
 	}
+
+	public Track GetByFileHash(string fileHash)
+	{
+		return _database.Tracks.FindOne(track => track.FileHash == fileHash);
+	}
 }