网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using Dpz.Core.Web.Cache;

namespace Dpz.Core.WebApi.Controllers;

/// <summary>
/// 音乐管理
/// </summary>
[ApiController, Route("api/[controller]")]
public class MusicController(
    IMusicService musicService,
    IObjectStorageOperation objectStorageService,
    ILogger<MusicController> logger
) : ControllerBase
{
    /// <summary>
    /// 音乐列表
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [ProducesResponseType<List<VmMusic>>(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetMusics([FromQuery] MusicQueryParameterDto parameter)
    {
        var musics = await musicService.GetPagesAsync(
            parameter.PageIndex,
            parameter.PageSize,
            parameter.Title
        );
        musics.AddPaginationMetadata(Response.Headers);
        return Ok(musics);
    }

    /// <summary>
    /// 单个音乐
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    [ProducesResponseType<VmMusic>(StatusCodes.Status200OK)]
    public async Task<IActionResult> GetMusic(string id)
    {
        var music = await musicService.GetAsync(id);
        return Ok(music);
    }

    /// <summary>
    /// 获取所有分组
    /// </summary>
    /// <returns></returns>
    [HttpGet("groups")]
    [ProducesResponseType<List<string>>(StatusCodes.Status200OK)]
    public async Task<ActionResult<List<string>>> GetGroups()
    {
        var groups = await musicService.GetGroupsAsync();
        return Ok(groups);
    }

    /// <summary>
    /// 获取歌词
    /// </summary>
    /// <param name="id"></param>
    /// <param name="httpClientFactory"></param>
    /// <returns></returns>
    [HttpGet("lrc/{id}"), CacheOutput(ServerTimeSpan = 30 * 24 * 60 * 60)]
    [ProducesResponseType<string>(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    public async Task<IActionResult> GetLyric(
        string id,
        [FromServices] IHttpClientFactory httpClientFactory
    )
    {
        if (string.IsNullOrEmpty(id))
            return NotFound();
        var music = await musicService.GetAsync(id);
        if (music == null)
            return NotFound();
        if (string.IsNullOrEmpty(music.LyricUrl))
        {
            return NoContent();
        }

        var httpClient = httpClientFactory.CreateClient("edge");
        HttpResponseMessage response;
        try
        {
            var request = new HttpRequestMessage(HttpMethod.Get, music.LyricUrl);
            response = await httpClient.SendAsync(request);
            if (!response.IsSuccessStatusCode)
            {
                return NoContent();
            }
        }
        catch (Exception e)
        {
            logger.LogError(e, "get lrc fail");
            return NotFound();
        }

        var lrc = await response.Content.ReadAsStringAsync();
        return Content(lrc, "application/lrc;charset=utf-8;");
    }

    /// <summary>
    /// 更改音乐信息
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    [HttpPatch("information"), Authorize(Policy = "System")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    public async Task<IActionResult> EditInformation([FromForm] VmChangeMusic model)
    {
        var information = new VmEditMusicInformation
        {
            Id = model.Id,
            Lyric = model.Lyric,
            Cover = model.Cover,
            Group = model.Group,
            UploadLyric = async (bytes, music) =>
            {
                if (!string.IsNullOrEmpty(music.LyricUrl))
                    await objectStorageService.DeleteAsync(music.LyricUrl);
                return await HandleUploadAsync(bytes, $"{Guid.NewGuid():N}.lrc,", "lyric");
            },
            UploadCover = async (bytes, music) =>
            {
                if (!string.IsNullOrEmpty(music.CoverUrl))
                    await objectStorageService.DeleteAsync(music.CoverUrl);
                string coverExt;
                try
                {
                    using var stream = new MemoryStream(bytes);
                    using var image = await Image.LoadAsync(stream);
                    coverExt =
                        image.Metadata.DecodedImageFormat?.FileExtensions.FirstOrDefault() ?? "jpg";
                }
                catch (Exception ex)
                {
                    coverExt = "jpg";
                    logger.LogError(ex, "get image format fail");
                }
                return await HandleUploadAsync(bytes, $"{Guid.NewGuid():N}.{coverExt}", "cover");
            }
        };
        await musicService.EditMusicInformationAsync(information);
        return NoContent();
    }

    /// <summary>
    /// 新增音乐
    /// </summary>
    /// <param name="upload"></param>
    /// <returns></returns>
    [HttpPost, Authorize(Policy = "System")]
    [RequestSizeLimit(104_857_600)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    public async Task<IActionResult> Save([FromForm] UploadMusicViewModel upload)
    {
        var from = string.IsNullOrWhiteSpace(upload.From) ? "Web Api" : upload.From;
        var model = new VmMusicUpload
        {
            From = from,
            Lyric = upload.Lyrics,
            Cover = upload.Cover,
            Music = upload.Music,
            UploadMusic = async (bytes, filename) => await HandleUploadAsync(bytes, filename, null),
            UploadCover = async (bytes, filename) =>
                await HandleUploadAsync(bytes, filename, "cover"),
            UploadLyric = async (bytes, filename) =>
                await HandleUploadAsync(bytes, filename, "lyric"),
            Group = upload.Group
        };
        await musicService.SaveAsync(model);
        return NoContent();
    }

    [NonAction]
    private async Task<string> HandleUploadAsync(byte[] bytes, string filename, string type)
    {
#if DEBUG
        var list = new List<string> { "Test", "music" };
#else
        var list = new List<string> { "music" };
#endif
        if (!string.IsNullOrEmpty(type))
            list.Add(type);
        var result = await objectStorageService.UploadAsync(bytes, list.ToArray(), filename);
        return result.AccessUrl;
    }

    /// <summary>
    /// 删除音乐
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpDelete("{id}"), Authorize(Policy = "System")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    public async Task<IActionResult> Delete(string id)
    {
        await musicService.DeleteAsync(
            id,
            async x => await objectStorageService.DeleteMusicAsync(x)
        );
        return NoContent();
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码是一个 ASP.NET Core Web API 控制器,名为 MusicController,用于管理音乐相关的操作。以下是对代码中各个部分的详细解释:

1. 控制器定义

  • MusicController 继承自 ControllerBase,并使用了 ApiControllerRoute 特性来定义 API 的路由。
  • 控制器依赖于三个服务:IMusicService(音乐服务)、IObjectStorageOperation(对象存储操作服务)和 ILogger<MusicController>(日志记录器)。

2. 音乐列表

  • 方法: GetMusics
  • HTTP 方法: GET
  • 功能: 获取音乐列表,支持分页和按标题搜索。返回的结果包含分页元数据。

3. 获取单个音乐

  • 方法: GetMusic
  • HTTP 方法: GET
  • 功能: 根据音乐 ID 获取单个音乐的详细信息。

4. 获取所有分组

  • 方法: GetGroups
  • HTTP 方法: GET
  • 功能: 获取所有音乐分组的列表。

5. 获取歌词

  • 方法: GetLyric
  • HTTP 方法: GET
  • 功能: 根据音乐 ID 获取歌词。使用 CacheOutput 特性缓存结果 30 天。若找不到歌词 URL 或请求失败,则返回相应的状态码。

6. 更改音乐信息

  • 方法: EditInformation
  • HTTP 方法: PATCH
  • 功能: 更新音乐的信息,包括歌词、封面和分组。支持文件上传,使用异步方法处理文件的上传和删除。

7. 新增音乐

  • 方法: Save
  • HTTP 方法: POST
  • 功能: 上传新的音乐文件,包括歌词和封面。支持文件上传,使用异步方法处理文件的上传。

8. 处理文件上传

  • 方法: HandleUploadAsync
  • 功能: 处理文件的上传逻辑,支持不同类型的文件(如音乐、歌词、封面)。根据环境(调试或生产)决定上传的目录。

9. 删除音乐

  • 方法: Delete
  • HTTP 方法: DELETE
  • 功能: 根据音乐 ID 删除音乐,并在删除时处理相关的对象存储操作。

总结

这个控制器提供了一整套音乐管理的 API,包括获取音乐列表、单个音乐信息、分组、歌词、更新音乐信息、新增音乐和删除音乐的功能。它使用了依赖注入来管理服务,并通过异步编程提高性能。控制器还实现了基本的错误处理和日志记录。

loading