using System.ComponentModel.DataAnnotations;
using Dpz.Core.EnumLibrary;
using Dpz.Core.Public.ViewModel.Request;
using Dpz.Core.Service.ObjectStorage.Services;

namespace Dpz.Core.Web.Controllers;

public class AudioController(
    IAudioService audioService,
    IObjectStorageOperation objectStorageService,
    IHttpCurrentUserService currentUserService
) : Controller
{
    [CheckAuthorize]
    public async Task<IActionResult> Upload(
        [FromForm, Required] IFormFile? record,
        [FromForm, Required] double duration
    )
    {
        if (record == null || record.Length == 0)
        {
            return Json(new ResultInfo("请上传音乐!"));
        }

        var audioExtensions = new[] { ".mp3", ".flac", ".wav", ".webm" };
        if (!audioExtensions.Contains(Path.GetExtension(record.FileName).ToLower()))
        {
            return Json(
                new ResultInfo($"目前只支持{string.Join("、", audioExtensions)}格式的音频!")
            );
        }

        var stream = record.OpenReadStream();
        var result = await objectStorageService.UploadAsync(
            stream,
            ["audio", DateTime.Now.ToString("yyyyMMdd")],
            $"{ObjectId.GenerateNewId()}.webm"
        );
        var request = new CreateAudioRequest
        {
            AccessUrl = result.Url,
            Duration = TimeSpan.FromSeconds(duration),
            Size = stream.Length,
            Uploader = await currentUserService.GetRequiredUserInfoAsync(),
            UploadTime = DateTime.Now,
        };

        var added = await audioService.AddAsync(request);
        return Json(new ResultInfo(added));
    }

    [CheckAuthorize, HttpPost]
    public async Task<IActionResult> Delete(string id)
    {
        var audio = await audioService.FindAsync(id);
        if (audio == null || User.RequiredNameIdentifier != audio.Uploader.Id)
        {
            return Json(new ResultInfo("未知音频或没有权限删除!"));
        }

        await audioService.DeleteAsync(id);
        return Json(new ResultInfo(true));
    }

    [CheckAuthorize]
    public async Task<IActionResult> MyAudio(int pageIndex, int pageSize = 20)
    {
        var user = await currentUserService.GetRequiredUserInfoAsync();
        var source = await audioService.GetPagesAsync(pageIndex, pageSize, user);
        return Json(source);
    }

    [CheckAuthorize(Permissions = Permissions.System)]
    public async Task<IActionResult> AudioPager(int pageIndex, int pageSize)
    {
        var source = await audioService.GetPagesAsync(pageIndex, pageSize);
        return Json(source);
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

代码解释

这是一个 ASP.NET Core MVC 的控制器类,用于处理音频文件的上传、删除和查询操作。

类结构

public class AudioController : Controller

依赖注入的服务

  • IAudioService - 音频业务逻辑服务
  • IObjectStorageOperation - 对象存储服务(用于文件上传)
  • IHttpCurrentUserService - 当前用户信息服务

使用了 C# 的主构造函数语法(Primary Constructor)进行依赖注入。


主要方法

1. Upload - 音频上传

[CheckAuthorize]
public async Task<IActionResult> Upload([FromForm, Required] IFormFile? record, [FromForm, Required] double duration)

功能:处理音频文件上传

参数

  • record - 表单上传的文件
  • duration - 音频时长(秒)

逻辑流程

  1. 验证文件是否为空
  2. 检查文件扩展名是否为支持的格式(.mp3, .flac, .wav, .webm
  3. 将文件上传到对象存储服务
    • 存储路径:audio/yyyyMMdd/
    • 文件名:使用 ObjectId 生成唯一 ID,扩展名为 .webm
  4. 创建音频记录请求对象 CreateAudioRequest,包含:
    • 访问URL
    • 时长
    • 文件大小
    • 上传者信息
    • 上传时间
  5. 保存音频信息到数据库
  6. 返回操作结果

2. Delete - 删除音频

[CheckAuthorize, HttpPost]
public async Task<IActionResult> Delete(string id)

功能:删除指定音频

权限控制

  • 需要用户认证
  • 只有音频上传者本人可以删除

逻辑流程

  1. 根据 ID 查找音频
  2. 验证音频是否存在且当前用户是否为上传者
  3. 执行删除操作
  4. 返回结果

3. MyAudio - 获取我的音频列表

[CheckAuthorize]
public async Task<IActionResult> MyAudio(int pageIndex, int pageSize = 20)

功能:分页查询当前用户上传的音频

参数

  • pageIndex - 页码
  • pageSize - 每页数量(默认20)

逻辑

  1. 获取当前用户信息
  2. 查询该用户的音频列表(分页)
  3. 返回数据

4. AudioPager - 管理员查询所有音频

[CheckAuthorize(Permissions = Permissions.System)]
public async Task<IActionResult> AudioPager(int pageIndex, int pageSize)

功能:分页查询所有音频(管理员功能)

权限要求Permissions.System(系统权限)

逻辑

  1. 分页查询所有音频
  2. 返回数据

关键特性

  1. 权限控制:使用自定义 [CheckAuthorize] 特性进行认证和授权
  2. 文件验证:限制上传文件格式和大小
  3. 对象存储:文件存储与业务数据分离
  4. ID 生成:使用 ObjectId 生成唯一标识符
  5. 分页查询:支持大数据量的音频列表查询
  6. 用户隔离:普通用户只能查看/删除自己的音频

潜在改进点

  • Upload 方法中文件扩展名为 .webm,但允许上传多种格式,可能需要格式转换逻辑
  • 缺少文件大小限制
  • 删除音频时未删除对象存储中的实际文件
评论加载中...