C#音乐播放器新增在线播放与音乐下载功能

前言

上次介绍了音乐播放器播放.mp3和,ogg文件,现在在该音乐播放器中新增在线播放和音乐下载功能。本文将详细介绍如何用C#为一个现有的音乐播放器添加这两个功能,并对实现过程中的关键代码进行分析。

一、需求分析

首先,我们需要明确在线播放与音乐下载功能的需求:

  1. 在线播放:用户可以通过输入音乐链接或搜索关键词来播放在线音乐。
  2. 音乐下载:用户可以选择将在线音乐下载到本地进行保存。

二、技术选型

为了实现上述功能,我们需要用到以下技术:

  • C#:作为主要的编程语言,用于编写音乐播放器的逻辑。
  • HttpClient:用于发起HTTP请求,获取在线音乐数据。
  • NAudio:用于处理音频数据的播放。
  • FileStream:用于处理文件写入,实现音乐下载功能。

三、实现步骤

(1)引入命名空间

using System.Diagnostics.Eventing.Reader;
using System.Threading;
using NAudio;
using NAudio.Wave;
using NAudio.Vorbis;
using System.Net;
using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

这部分代码引入了所需的命名空间,以便在程序中使用相关的类和方法。具体来说:

  • System.Diagnostics.Eventing.Reader:这个命名空间包含了用于读取事件日志的类和方法。
  • System.Threading:这个命名空间包含了多线程编程的相关类和方法,如线程池、锁等。
  • NAudio:这是一个音频处理库,提供了音频播放、录制、转换等功能。
  • NAudio.Wave:这是NAudio库中的一个子命名空间,提供了对WAV格式音频文件的处理功能。
  • NAudio.Vorbis:这是NAudio库中的一个子命名空间,提供了对Ogg Vorbis格式音频文件的处理功能。
  • System.Net:这个命名空间包含了网络编程的相关类和方法,如HTTP请求、FTP上传下载等。
  • System.Text:这个命名空间包含了文本处理的相关类和方法,如字符串操作、编码解码等。
  • System.Net.Http:这个命名空间包含了基于HTTP协议的网络编程相关类和方法,如HTTP客户端、HTTP响应等。
  • System.Threading.Tasks:这个命名空间包含了异步编程的相关类和方法,如任务、异步方法等。
  • System.Text.RegularExpressions:这个命名空间包含了正则表达式的相关类和方法,用于进行字符串匹配和替换等操作。

(2)设置连接的网站:

​
private const string audioUrl = "http://tool.liumingye.cn/music/?page=homePage";

​

这部分代码定义了一个常量字符串audioUrl,它表示要下载音频文件的网址。这个网址是一个在线音频文件的链接。

(3)点击按键事件处理

private async void button1_Click(object sender, EventArgs e)
{
    await DownloadAudioAsync(audioUrl);
}

button1_Click方法:处理打开文件对话框选择音频文件的事件。当用户点击按钮时,会弹出一个文件选择对话框,用户可以选择一个或多个音频文件。选择的文件路径会被存储在localmusiclist列表中,并显示在listBox1列表框中。

button2_Click方法:处理播放/暂停/停止音频的事件。当用户点击按钮时,会根据当前的状态切换音频的播放状态。

button3_Click方法:处理下一首音频的事件。当用户点击按钮时,会选择listBox1列表框中的下一首音频进行播放。

button5_Click方法:处理下载在线音频文件的事件。当用户点击按钮时,会调用DownloadAudioAsync方法异步下载在线音频文件。

这里用的例子是button1的点击事件处理方法

(4)下载音乐文件方法

private async Task DownloadAudioAsync(string url)
{
    using (var httpClient = new HttpClient())
    {
        try
        {
            // 发起 GET 请求并获取响应
            using (var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
            {
                response.EnsureSuccessStatusCode(); // 确保响应成功
                using (var stream = await response.Content.ReadAsStreamAsync())
                {
                    // 获取文件名,如果服务器没有提供文件名,可以自行指定
                    var fileName = GetFileName(response);

                    // 指定保存文件的路径,这里保存在当前用户的下载目录下
                    var filePath = Path.Combine(@"D:\Desktop", fileName);

                    // 使用 FileStream 写入文件
                    using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                    {
                        await stream.CopyToAsync(fileStream);
                    }

                    MessageBox.Show("下载完成:" + filePath, "下载成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"下载失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

这部分代码定义了一个异步方法DownloadAudioAsync,用于异步下载在线音频文件。它接收一个网址参数,然后使用HttpClient发起GET请求获取响应。如果响应成功,它将从响应内容中读取音频数据,并将其保存到本地文件中。如果在下载过程中发生异常,将显示错误消息框。具体来说:

httpClient是一个HttpClient对象,用于发送HTTP请求和接收HTTP响应。

response是一个HttpResponseMessage对象,表示HTTP响应。

stream是一个Stream对象,表示HTTP响应的内容流。

fileName是一个字符串变量,表示要保存的文件名。

filePath是一个字符串变量,表示要保存的文件路径。

fileStream是一个FileStream对象,用于将HTTP响应的内容流写入到本地文件中。

四、完整代码

using System.Diagnostics.Eventing.Reader;
using System.Threading;
using NAudio;
using NAudio.Wave;
using NAudio.Vorbis;
using System.Diagnostics;
using System.Net;
using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace WinFormsApp
{
    public partial class Form1 : Form
    {
        string[] files;
 
        List<string> localmusiclist = new List<string> { };
 
        public Form1()
        {
            InitializeComponent();
        }
        private void musicplay(string filename)
        {
            axWindowsMediaPlayer1.URL = filename;
            string extension = Path.GetExtension(filename);
 
            if (extension == ".ogg") { Console.WriteLine("这是.ogg文件"); }
            else if (extension == ".mp3") // 最好也检查一下扩展名是否存在  
            {
                axWindowsMediaPlayer1.Ctlcontrols.play();
            }
            else
            {
                // 处理没有扩展名或无法识别的文件  
                Console.WriteLine("无法识别的文件格式");
            }
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "选择音频|*.mp3";//;*.flac;*.wav
            openFileDialog1.Multiselect = true;
 
            if (openFileDialog1.ShowDialog() == DialogResult.OK)//用户点击确定按钮
            {
                listBox1.Items.Clear();//上一次的结果不会影响到下一次
                localmusiclist.Clear();
 
                if (files != null)
                {
                    Array.Clear(files, 0, files.Length);//把array里面的所有元素设置为默认,并清空
                }
 
                files = openFileDialog1.FileNames;//这个选择多个文件,filename选择一个文件
                string[] array = files;
                foreach (string x in array)
                {
                    listBox1.Items.Add(x);
                    localmusiclist.Add(x);//选择多个音乐文件,能以行显示
                }
 
            }
        }
 
        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (localmusiclist.Count > 0)
            {
                axWindowsMediaPlayer1.URL = localmusiclist[listBox1.SelectedIndex];
                //axWindowsMediaPlayer1.Ctlcontrols.play();
                musicplay(axWindowsMediaPlayer1.URL);
                label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[listBox1.SelectedIndex]);
            }
        }
 
        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            axWindowsMediaPlayer1.Ctlcontrols.stop();
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            if (localmusiclist.Count > 0)
            {
                int index = listBox1.SelectedIndex + 1;
 
                if (index >= localmusiclist.Count())
                {
                    index = 0;
                }
 
                axWindowsMediaPlayer1.URL = localmusiclist[index];
                //axWindowsMediaPlayer1.Ctlcontrols.play();
                musicplay(axWindowsMediaPlayer1.URL);
                label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[index]);
 
                listBox1.SelectedIndex = index;
            }
        }
 
        private void button4_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "打开音频|*.ogg";
            string oggFilePath = "";
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                oggFilePath = openFileDialog.FileName;
            }
            using (var reader = new VorbisWaveReader(oggFilePath))
            {
                using (var outputDevice = new WaveOutEvent())
                {
                    outputDevice.Init(reader);
                    outputDevice.Play();
 
                    // 等待播放完成或按需添加其他逻辑  
                    while (outputDevice.PlaybackState == PlaybackState.Playing)
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                }
            }
 
        }
 
        private void axWindowsMediaPlayer1_Enter(object sender, EventArgs e)
        {
 
        }
 
        private const string audioUrl = "http://tool.liumingye.cn/music/?page=homePage";
 
        private async void button5_Click(object sender, EventArgs e)
        {
            await DownloadAudioAsync(audioUrl);
        }
 
        private async Task DownloadAudioAsync(string url)
        {
            using (var httpClient = new HttpClient())
            {
                try
                {
                    // 发起 GET 请求并获取响应
                    using (var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
                    {
                        response.EnsureSuccessStatusCode(); // 确保响应成功
                        using (var stream = await response.Content.ReadAsStreamAsync())
                        {
                            // 获取文件名,如果服务器没有提供文件名,可以自行指定
                            var fileName = GetFileName(response);
 
                            // 指定保存文件的路径,这里保存在当前用户的下载目录下
                            var filePath = Path.Combine(@"D:\Desktop", fileName);
 
                            // 使用 FileStream 写入文件
                            using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                            {
                                await stream.CopyToAsync(fileStream);
                            }
 
                            MessageBox.Show("下载完成:" + filePath, "下载成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"下载失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
 
        private string GetFileName(HttpResponseMessage response)
        {
            // 从响应头或 URL 中获取文件名
            string fileName = null;
            if (!string.IsNullOrEmpty(response.Content.Headers.ContentDisposition?.FileName))
            {
                fileName = response.Content.Headers.ContentDisposition.FileName;
            }
            else
            {
                Uri.TryCreate(response.RequestMessage.RequestUri.ToString(), UriKind.Absolute, out Uri uri);
                fileName = Path.GetFileName(uri.LocalPath);
            }
            return fileName;
        }
 
    }
}

五、代码难点分析

  1. 音频文件格式识别:根据文件扩展名判断音频文件格式,需要处理没有扩展名或无法识别的文件格式。

  2. 音频播放控制:使用axWindowsMediaPlayer1控件播放音频,需要掌握其API使用方法,如URL属性设置音频文件路径,Ctlcontrols.play()方法播放音频等。

  3. 列表框与音频文件关联:通过listBox1显示已选择的音频文件列表,需要实现列表框中选中项与音频文件的关联,以便在播放时正确选择对应的音频文件。

  4. 异步下载:使用HttpClient异步下载在线音频文件,需要理解异步编程的概念,如asyncawait关键字的使用,以及Task类的使用。

  5. 异常处理:在下载过程中可能会遇到异常,如网络错误、文件写入错误等,需要对异常进行处理,避免程序崩溃。

  • 35
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值