New endpoint

New endpoint to upload song with metadata and cover art as separate entities
This commit is contained in:
kdeng00
2021-12-29 14:06:52 -05:00
parent aa0a1ab5fe
commit 3a6e0f64bc
10 changed files with 221 additions and 40 deletions
+31 -1
View File
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Configuration;
using System.IO;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Icarus.Constants;
using Icarus.Controllers.Utilities;
using Icarus.Database.Contexts;
@@ -118,6 +120,34 @@ namespace Icarus.Controllers.Managers
return null;
}
public CoverArt SaveCoverArt(IFormFile data, Song song)
{
var cover = new CoverArt { SongTitle = song.Title };
try
{
var dirMgr = new DirectoryManager(_rootCoverArtPath);
var defaultExtension = ".png";
dirMgr.CreateDirectory(song);
var segment = cover.GenerateFilename(0);
var imagePath = dirMgr.SongDirectory + segment + defaultExtension;
cover.ImagePath = imagePath;
using (var fileStream = new FileStream(imagePath, FileMode.Create))
{
data.CopyTo(fileStream);
}
}
catch (Exception ex)
{
_logger.Error(ex.Message, "An error occurred");
}
return cover;
}
public CoverArt GetCoverArt(Song song)
{
return _coverArtContext.CoverArtImages.FirstOrDefault(cov => cov.SongTitle.Equals(song.Title));
+63 -18
View File
@@ -176,27 +176,24 @@ namespace Icarus.Controllers.Managers
_logger.Info("Starting the process of saving the song to the filesystem");
var song = await SaveSongTemp(songFile);
System.IO.File.Delete(song.SongPath());
DirectoryManager dirMgr = new DirectoryManager(_config, song);
dirMgr.CreateDirectory();
var fileDir = dirMgr.SongDirectory;
var filePath = fileDir;
var songFilename = song.Filename;
if (!songFilename.EndsWith(".mp3"))
filePath += $"{songFilename}.mp3";
else
filePath += $"{songFilename}";
var filePath = dirMgr.SongDirectory;
filePath += $"{song.Filename}";
_logger.Info($"Absolute song path: {filePath}");
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await (songFile.CopyToAsync(fileStream));
song.SongDirectory = fileDir;
var songBytes = await System.IO.File.ReadAllBytesAsync(song.SongPath());
System.IO.File.WriteAllBytesAsync(filePath, songBytes);
System.IO.File.Delete(song.SongPath());
song.SongDirectory = dirMgr.SongDirectory;
_logger.Info("Song successfully saved to filesystem");
}
@@ -214,6 +211,55 @@ namespace Icarus.Controllers.Managers
}
}
public async Task SaveSongToFileSystem(IFormFile songFile, IFormFile coverArtData, Song song)
{
if (string.IsNullOrEmpty(song.Filename))
{
song.Filename = song.GenerateFilename(1);
}
song.SongDirectory = _tempDirectoryRoot;
song.DateCreated = DateTime.Now;
using (var filestream = new FileStream(song.SongPath(), FileMode.Create))
{
_logger.Info("Saving song to temporary directory");
await songFile.CopyToAsync(filestream);
}
var coverMgr = new CoverArtManager(_config);
var coverArt = coverMgr.SaveCoverArt(coverArtData, song);
var meta = new MetadataRetriever();
song.Duration = meta.RetrieveSongDuration(song.SongPath());
// const int trackCount = meta.RetrieveTrackCount(song.)
meta.UpdateMetadata(song, song);
meta.UpdateCoverArt(song, coverArt);
DirectoryManager dirMgr = new DirectoryManager(_config, song);
dirMgr.CreateDirectory();
var filePath = dirMgr.SongDirectory + song.Filename;
_logger.Info($"Absolute song path: {filePath}");
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
var songBytes = await System.IO.File.ReadAllBytesAsync(song.SongPath());
await System.IO.File.WriteAllBytesAsync(filePath, songBytes);
System.IO.File.Delete(song.SongPath());
song.SongDirectory = dirMgr.SongDirectory;
_logger.Info("Song successfully saved to filesystem");
}
coverMgr.SaveCoverArtToDatabase(ref song, ref coverArt);
SaveSongToDatabase(song);
}
public async Task<SongData> RetrieveSong(Song songMetaData)
@@ -248,22 +294,21 @@ namespace Icarus.Controllers.Managers
private async Task<Song> SaveSongTemp(IFormFile songFile)
{
var song = new Song();
var filename = song.GenerateFilename();
var filePath = Path.Combine(_tempDirectoryRoot, filename);
_logger.Info("Assigning song filename");
song.SongDirectory = _tempDirectoryRoot;
song.Filename = song.GenerateFilename(1);
using (var filestream = new FileStream(filePath, FileMode.Create))
using (var filestream = new FileStream(song.SongPath(), FileMode.Create))
{
_logger.Info("Saving song to temporary directory");
await songFile.CopyToAsync(filestream);
}
MetadataRetriever meta = new MetadataRetriever();
song = meta.RetrieveMetaData(filePath);
song = meta.RetrieveMetaData(song.SongPath());
_logger.Info("Assigning song filename");
song.Filename = filename;
song.SongDirectory = _tempDirectoryRoot;
song.Filename = song.GenerateFilename(1);
song.DateCreated = DateTime.Now;
return song;
+62 -6
View File
@@ -81,13 +81,21 @@ namespace Icarus.Controllers.Utilities
_genre = string.Join("", fileTag.Tag.Genres);
_year = (int)fileTag.Tag.Year;
_duration = (int)fileTag.Properties.Duration.TotalSeconds;
var albumArtist = string.Join("", fileTag.Tag.AlbumArtists);
var track = (int)fileTag.Tag.Track;
var disc = (int)fileTag.Tag.Disc;
song.Title = _title;
song.Artist = _artist;
song.AlbumTitle = _album;
song.AlbumArtist = albumArtist;
song.Genre = _genre;
song.Year = _year;
song.Duration = _duration;
song.Track = track;
song.Disc = disc;
song.TrackCount = (int)fileTag.Tag.TrackCount;
song.DiscCount = (int)fileTag.Tag.DiscCount;
}
catch (Exception ex)
{
@@ -100,6 +108,15 @@ namespace Icarus.Controllers.Utilities
return song;
}
public int RetrieveSongDuration(string filepath)
{
var duration = 0;
var fileTag = TagLib.File.Create(filepath);
duration = (int)fileTag.Properties.Duration.TotalSeconds;
return duration;
}
public byte[] RetrieveCoverArtBytes(Song song)
{
try
@@ -162,6 +179,11 @@ namespace Icarus.Controllers.Utilities
var album = updatedSong.AlbumTitle;
var genre = updatedSong.Genre;
var year = updatedSong.Year;
var albumArtist = updatedSong.AlbumArtist;
var track = updatedSong.Track;
var trackCount = updatedSong.TrackCount;
var disc = updatedSong.Disc;
var discCount = updatedSong.DiscCount;
TagLib.File fileTag = TagLib.File.Create(filePath);
try
@@ -196,6 +218,26 @@ namespace Icarus.Controllers.Utilities
_updatedSong.Year = year;
fileTag.Tag.Year = (uint)year;
break;
case "albumartist":
_updatedSong.AlbumArtist = albumArtist;
fileTag.Tag.AlbumArtists = new []{albumArtist};
break;
case "track":
_updatedSong.Track = track;
fileTag.Tag.Track = (uint)(track);
break;
case "trackcount":
_updatedSong.TrackCount = trackCount;
fileTag.Tag.TrackCount = (uint)(trackCount);
break;
case "disc":
_updatedSong.Disc = disc;
fileTag.Tag.Disc = (uint)(disc);
break;
case "disccount":
_updatedSong.DiscCount = discCount;
fileTag.Tag.DiscCount = (uint)(discCount);
break;
}
}
@@ -264,13 +306,13 @@ namespace Icarus.Controllers.Utilities
songValues["Artists"] = String.IsNullOrEmpty(song.Artist);
songValues["Album"] = String.IsNullOrEmpty(song.AlbumTitle);
songValues["Genre"] = String.IsNullOrEmpty(song.Genre);
songValues["AlbumArtist"] = String.IsNullOrEmpty(song.AlbumArtist);
if (song.Year == null)
songValues["Year"] = true;
else if (song.Year == 0)
songValues["Year"] = true;
else
songValues["Year"] = false;
songValues["Year"] = CheckIntField(song.Year);
songValues["Track"] = CheckIntField(song.Track);
songValues["TrackCount"] = CheckIntField(song.TrackCount);
songValues["Disc"] = CheckIntField(song.Disc);
songValues["DiscCount"] = CheckIntField(song.Disc);
Console.WriteLine("Checking for null data completed");
_logger.Info("Checking for null data completed");
@@ -284,6 +326,20 @@ namespace Icarus.Controllers.Utilities
return songValues;
}
private bool CheckIntField(int? value)
{
if (value == null)
{
return true;
}
else if (value == 0)
{
return true;
}
return false;
}
#endregion
}
}
+51
View File
@@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Icarus.Controllers.Managers;
using Icarus.Models;
@@ -60,6 +61,18 @@ namespace Icarus.Controllers.V1
return File(song.Data, "application/x-msdownload", songMetaData.Filename);
}
// Assumes that the song already has metadata such as
// Title
// Artist
// Album
// Genre
// Year
// Track
// Track count
// Disc
// Disc count
// Cover art
//
[HttpPost("upload"), DisableRequestSizeLimit]
[Route("private-scoped")]
[Authorize("upload:songs")]
@@ -93,6 +106,33 @@ namespace Icarus.Controllers.V1
return NotFound();
}
// The client is expected to send the file, metadata, and cover art separately.
// Any metadata already on the file will be overwritten with values from the metadata
// as well as the cover art
//
[HttpPost("upload/with/data")]
[Route("private-scoped")]
[Authorize("upload:songs")]
public async Task<IActionResult> Post ([FromForm] UploadSongWithDataForm up)
{
try
{
if (up.SongData.Length > 0 && up.CoverArtData.Length > 0 && !string.IsNullOrEmpty(up.SongFile))
{
var song = Newtonsoft.Json.JsonConvert.DeserializeObject<Song>(up.SongFile);
_logger.LogInformation($"Song title: {song.Title}");
await _songMgr.SaveSongToFileSystem(up.SongData, up.CoverArtData, song);
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message, "An error occurred");
}
return Ok();
}
[HttpDelete("delete/{id}")]
[Authorize("delete:songs")]
public IActionResult Delete(int id)
@@ -117,6 +157,17 @@ namespace Icarus.Controllers.V1
return Ok();
}
}
public class UploadSongWithDataForm
{
[FromForm(Name = "file")]
public IFormFile SongData { get; set; }
[FromForm(Name = "cover")]
public IFormFile CoverArtData { get; set; }
[FromForm(Name = "metadata")]
public string SongFile { get; set; }
}
}
}