You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Server音频列表:如何实现播放与删除功能?

Blazor Server音频列表功能实现方案

核心功能实现思路

针对点击文件名触发播放/删除操作的需求,采用模态框选择操作 + JSInterop控制音频播放 + 后端文件操作刷新列表的方案,具体实现如下:


1. 前端代码修改(含模态框与音频元素优化)

替换原前端代码,添加操作选择模态框,并为每个音频元素设置唯一ID:

<div class="table-wrapper-scroll-y my-custom-scrollbar">
    <table class="table table-bordered table-striped mb-0">
        <tbody>
            @if (filesList != null && filesList.Count > 0)
            {
                int auF = 0;  
                @foreach (string file in filesList)
                {    
                    auF++;
                    <tr> 
                        <td>
                            <span>@auF.</span>
                            <span @onclick="() => ShowFileActionModal(file)" style="cursor:pointer; text-decoration: underline; color: blue;">@file</span>
                        </td> 
                        <td>
                            <audio controls="controls" id="@($"audio-{file}")">
                                <source src="@GetAudioFileUrl(file)">
                            </audio>
                        </td> 
                    </tr>
                }
            }
            else
            {
                <tr>
                    <td colspan="2">No Files</td>
                </tr>
            }
        </tbody>
    </table>
</div>

<!-- 操作选择模态框 -->
<div class="modal fade" id="fileActionModal" tabindex="-1" aria-labelledby="fileActionModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="fileActionModalLabel">操作选择</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                请选择对 <strong>@currentFileName</strong> 的操作:
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary" @onclick="PlaySelectedAudio" data-bs-dismiss="modal">播放音频</button>
                <button type="button" class="btn btn-danger" @onclick="DeleteSelectedFile" data-bs-dismiss="modal">删除文件</button>
            </div>
        </div>
    </div>
</div>

2. 后端代码修改(含文件操作与JSInterop调用)

注入必要服务,实现模态框控制、音频播放、文件删除与列表刷新:

@inject IJSRuntime JSRuntime
@inject IWebHostEnvironment WebHostEnv

@code{
    List<string> filesList = new List<string>();
    string audioFolderPath;
    string currentFileName;

    protected override void OnInitialized()
    {
        // 推荐将音频文件夹放在wwwroot下,简化前端访问
        audioFolderPath = Path.Combine(WebHostEnv.WebRootPath, "audio");
        // 若需保留原路径,替换为:
        // audioFolderPath = Path.Combine(Directory.GetCurrentDirectory(), "path");
        
        LoadAudioFiles();
    }

    // 加载音频文件列表
    void LoadAudioFiles()
    {
        filesList.Clear();
        if (Directory.Exists(audioFolderPath))
        {
            var files = Directory.GetFiles(audioFolderPath)
                                 .Select(Path.GetFileName)
                                 .ToList();
            filesList.AddRange(files);
        }
    }

    // 显示操作选择模态框
    async Task ShowFileActionModal(string fileName)
    {
        currentFileName = fileName;
        await JSRuntime.InvokeVoidAsync("bootstrap.Modal.getOrCreateElement", "#fileActionModal").InvokeVoidAsync("show");
    }

    // 获取音频文件的前端访问URL
    string GetAudioFileUrl(string fileName)
    {
        // 音频在wwwroot/audio下的情况
        return $"/audio/{Uri.EscapeDataString(fileName)}";
        
        // 音频不在wwwroot时,需配合API控制器使用:
        // return $"/api/audio/{Uri.EscapeDataString(fileName)}";
    }

    // 播放选中的音频
    async Task PlaySelectedAudio()
    {
        if (!string.IsNullOrEmpty(currentFileName))
        {
            var audioElementId = $"audio-{currentFileName}";
            await JSRuntime.InvokeVoidAsync("playAudio", audioElementId);
        }
    }

    // 删除选中的文件并刷新列表
    async Task DeleteSelectedFile()
    {
        if (!string.IsNullOrEmpty(currentFileName))
        {
            var fullFilePath = Path.Combine(audioFolderPath, currentFileName);
            try
            {
                if (File.Exists(fullFilePath))
                {
                    File.Delete(fullFilePath);
                    LoadAudioFiles();
                    StateHasChanged(); // 通知UI更新
                }
            }
            catch (Exception ex)
            {
                await JSRuntime.InvokeVoidAsync("alert", $"删除失败:{ex.Message}");
            }
        }
    }
}

3. 补充JS代码(控制音频播放)

在_Host.cshtml或组件底部添加以下脚本:

<script>
    function playAudio(elementId) {
        const audioElement = document.getElementById(elementId);
        if (audioElement) {
            audioElement.play().catch(err => console.error('播放失败:', err));
        }
    }
</script>

关键注意事项

  • 音频路径处理:
    • 优先将音频文件夹放在wwwroot/audio下,前端可直接通过相对路径访问。
    • 若必须使用非wwwroot路径,需创建API控制器返回文件流(示例代码如下):
      [ApiController]
      [Route("api/[controller]")]
      public class AudioController : ControllerBase
      {
          private readonly string _audioPath = Path.Combine(Directory.GetCurrentDirectory(), "path");
      
          [HttpGet("{fileName}")]
          public IActionResult GetAudio(string fileName)
          {
              var filePath = Path.Combine(_audioPath, fileName);
              if (!File.Exists(filePath)) return NotFound();
              
              var contentType = Path.GetExtension(fileName).ToLowerInvariant() switch
              {
                  ".mp3" => "audio/mpeg",
                  ".wav" => "audio/wav",
                  ".ogg" => "audio/ogg",
                  _ => "application/octet-stream"
              };
              return File(System.IO.File.OpenRead(filePath), contentType);
          }
      }
      
  • Bootstrap依赖:确保项目已引入Bootstrap 5的CSS与JS文件,以支持模态框功能。

内容的提问来源于stack exchange,提问作者Addlon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 19:50:39