C#实现音乐在线播放和下载——Windows程序设计作业3

1. 作业内容

    编写一个C#程序,在作业二实现的本地播放功能的基础上,新增在线播放和在线下载功能,作业二博客地址:C#实现简单音乐文件解析播放——Windows程序设计作业2

2. 架构选择

    考虑到需求中的界面友好和跨版本兼容性,我选择选择WinForms作为开发平台,WinForms提供了一个简单而强大的方法来创建桌面应用程序,并且与C#高度兼容,在开发过程,选择.NETFramework 4.8.0版本进行程序设计。

3. UI设计

    在本次程序设计中,我设计了一套UI界面,并且利用panelbutton控件实现简单的界面切换,一共分为三个界面:本地播放界面、在线下载界面和在线播放界面,具体界面如下:

此处使用的图标来源:FLATICON

本地播放节目
在线下载界面
在线播放界面
    以下为本次作业涉及到的控件:
    1) Button:用于输入歌名实现搜索功能。
    2) TextBox:用于触发各种操作,例如播放、搜索、下载等。
    3) Panel:用于切换界面。
    4) ListBox:下载用于显示搜索结果列表或歌单列表,用户可以从中选择歌曲。
    5) ProgressBar:用于显示进度。
    6) AxWindowsMediaPlayer:用于播放音乐。

4. 主界面设计

    主界面中主要是围绕各个界面的切换设置的,其中将本地播放音乐界面作为主界面UCHome,剩余两个功能界面定义为UserControl对象。

// 定义各界面对象
public UCHome uchome;
public UserControl1 userControl1;
public UserControl2 userControl2;

    切换界面的思路是,利用panel控件作为主要的切换面板,在切换界面的时候,清空其中的界面并添加新的界面,从而实现界面切换功能。

uchome = new UCHome();    //实例化
uchome.Show(); // 将窗体一进行显示
panelContain.Controls.Clear(); // 清空原容器上的控件
panelContain.Controls.Add(uchome); // 将窗体一加入容器panelContain

5. 音乐API说明

    在本次作业中,设计在线下载和播放使用的音乐api接口是调用了别人进行二次加工后的api接口,简化了开发流程,特别感谢,但不方便透露,故不在此展出,项目链接在最后放出,如有需要,在下载后调整api接口和返回的参数信息处理,仍可实现功能。

6. 功能说明与代码实现

6.1 本地播放音乐

    此项功能主要是辨析音乐文件的格式并且针对不同格式的文件采取不同的解析方式,在作业二中已经实现,此处不再过多阐述。

6.2 在线下载音乐

    在线下载音乐功能可以分为三个模块实现:搜索歌曲、选择想要下载的歌曲、下载音乐,最终效果如下:

6.2.1 搜索歌曲

    搜索歌曲模块通过用户输入的歌曲名称,向远程API发送请求并获取搜索结果。
    1) 初始化参数

private int selectedIndex = -1; // 当前选中的索引
private List<string> responseLines = new List<string>(); // 保存响应结果的列表

    2) 用户在文本框TextBox中输入歌曲名称。

string songName = textBox1.Text;
if (string.IsNullOrWhiteSpace(songName))
{MessageBox.Show("请输入歌曲名称");return;
}

    3) 点击搜索按钮后,调用SearchSongsAsync方法发送HTTP请求,获取包含搜索结果的响应,将结果处理好显示在ListBox中供用户选择。

private async void button1_Click(object sender, EventArgs e)
{	/*此处省略了前面的输入部分*/listBox1.Items.Clear();responseLines.Clear();var responseBody = await SearchSongsAsync(songName); // 调用搜索歌曲的异步方法if (!string.IsNullOrEmpty(responseBody)){var lines = responseBody.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);foreach (var line in lines){responseLines.Add(line);listBox1.Items.Add(line); // 将结果添加到列表框中}}else{MessageBox.Show("未找到歌曲");}
}private async Task<string> SearchSongsAsync(string songName)
{string apiUrl = $"https://www.zbx123456?msg={Uri.EscapeDataString(songName)}";using (HttpClient client = new HttpClient()){HttpResponseMessage response = await client.GetAsync(apiUrl);response.EnsureSuccessStatusCode();string responseBody = await response.Content.ReadAsStringAsync();return responseBody;}
}

    此处采取async修饰函数和Task<string>作为返回值是因为在WindoForms应用程序中,如果进行长时间的同步操作(如网络请求、文件读写),会导致界面卡顿或无响应。通过使用asyncTask,可以将这些耗时操作异步执行,从而保持用户界面的响应能力。
    其中,async 用于声明异步方法,允许函数中使用await函数,await允许程序在执行异步操作时,暂停方法执行,释放UI线程以处理其他任务。当异步操作完成后,恢复方法执行。
    Task<string>表示一个异步操作,该操作最终会返回一个string结果,使异步方法在逻辑上与同步方法一致,方便处理返回值。

6.2.2 选择想要下载的歌曲

    用户在搜索结果列表中选择想要下载的歌曲,通过SelectedIndexChanged事件处理程序更新选中的索引。

// 列表框选中项改变事件处理程序
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{selectedIndex = listBox1.SelectedIndex + 1;
}

6.2.3 下载音乐

    下载音乐模块根据选中的歌曲索引获取下载链接,并下载音乐文件到用户指定的路径。
    1) 用户点击下载按钮,调用button2_Click事件处理程序,先检查是否有选中的歌曲,并异步获取下载链接。

private async void button2_Click(object sender, EventArgs e)
{if (selectedIndex == -1 || selectedIndex >= responseLines.Count){MessageBox.Show("请选择要下载的歌曲");return;}string downloadUrl = await GetDownloadUrlAsync(selectedIndex); // 调用获取下载链接的异步方法/*下载音乐逻辑,后面详细介绍*/
}

    2) 调用GetDownloadUrlAsync方法获取选中歌曲的下载链接:

private async Task<string> GetDownloadUrlAsync(int n)
{string apiUrl = $"https://www.zbx123456?msg={Uri.EscapeDataString(textBox1.Text)}&n={n}";using (HttpClient client = new HttpClient()){HttpResponseMessage response = await client.GetAsync(apiUrl);response.EnsureSuccessStatusCode();string responseBody = await response.Content.ReadAsStringAsync();textBox2.Text = responseBody; // 将响应内容放入textBox2中// 检查响应内容,解析播放链接var lines = responseBody.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);foreach (var line in lines){if (line.StartsWith("播放链接:")){return line.Substring(5).Trim();}}}return null;
}

    这里需要对api接口重新处理使因为在搜索歌曲后,根据选择的歌曲不同,api接口中的参数需要进行调整才能返回这首歌曲的详细参数,其中的播放链接指向这首歌曲的下载地址,利用这个地址,便可以在线下载音乐。
    3) 弹出提示,用户自行选择下载路径,选择后,调用DownloadSongAsync方法去下载音乐。

if (!string.IsNullOrEmpty(downloadUrl)){string fileName = $"{Guid.NewGuid()}.flac"; // 用GUID作为文件名using (SaveFileDialog saveFileDialog = new SaveFileDialog()){saveFileDialog.FileName = fileName;saveFileDialog.Filter = "FLAC files (*.flac)|*.flac|All files (*.*)|*.*";if (saveFileDialog.ShowDialog() == DialogResult.OK){progressBar1.Value = 0; // 重置进度条await DownloadSongAsync(downloadUrl, saveFileDialog.FileName); // 调用下载歌曲的异步方法MessageBox.Show("下载完成");}}}else{MessageBox.Show("未找到播放链接");}

    4) 下载文件,并提示下载进度

private async Task DownloadSongAsync(string url, string filePath)
{//设置最长响应时间:30minusing (HttpClient client = new HttpClient { Timeout = TimeSpan.FromMinutes(30) }){// 获取响应流using (HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)){//确保响应成功response.EnsureSuccessStatusCode();long? totalBytes = response.Content.Headers.ContentLength;using (Stream contentStream = await response.Content.ReadAsStreamAsync(),fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true)){var buffer = new byte[8192];long totalReadBytes = 0;int readBytes;while ((readBytes = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0){await fileStream.WriteAsync(buffer, 0, readBytes);totalReadBytes += readBytes;if (totalBytes.HasValue){// 更新进度条progressBar1.Value = (int)((totalReadBytes * 100) / totalBytes.Value);}}}}}
}

    这里同样采取awaitTask设计,除此之外,此处利用response.Content.Headers.ContentLength获取响应内容的总字节大小,并采取HTTP客户端->缓冲区->文件的流程下载文件,在下载中记录目前已经下载的字节数totalReadBytes,实现下载进度条。
    至此,整个在线下载音乐功能实现完毕,用户可以自己搜索关键词,下载音乐。

疑似咪咕音乐的资源不多,能选的有点少~

6.3 在线播放音乐

    在线下载音乐功能可以分为三个模块实现:搜索歌曲、选择想要播放的歌曲、播放音乐,实现效果如下:

6.3.1 搜索歌曲 && 6.3.2 选择想要播放的歌曲

    此处的实现思路和在线下载音乐的思路一样的,不在此展出了。

6.3.3 播放音乐

    用户点击播放按钮,调用button3_Click事件处理程序,先检查是否有选中的歌曲,并异步调用GetPlayUrlAsync方法获取播放链接,将链接传入PlayAudio函数中调用AxWindowsPlayer控件实现在线播放功能:
    button3_click的代码实现如下:

private async void button3_Click(object sender, EventArgs e)
{if (selectedIndex == -1 || selectedIndex >= responseLines.Count){MessageBox.Show("请选择要播放的歌曲");return;}string playUrl = await GetPlayUrlAsync(selectedIndex); // 调用获取播放链接的异步方法if (!string.IsNullOrEmpty(playUrl)){PlayAudio(playUrl); // 调用播放音乐的方法}else{MessageBox.Show("未找到播放链接");}
}

    GetPlayUrlAsync方法与前面的 GetDownloadUrlAsync方法几乎一致,只改变了函数名,就不展示了~
    PlayAudio函数中调用AxWindowsPlayer控件实现在线播放功能,在作业二中只使用了该控件的本地播放功能,其实它可以通过传递url参数实现在线播放功能。

不得不说,查文档大的时候才意识到,可能上课讲过,一下子记不得了,折腾了好久,原来的思路是使用WebBrower控件去实现,这样的缺点是,播放器是调用的本地自己的播放器,不太方便,故选用这种方式。

public void PlayAudio(string url)
{axWindowsMediaPlayer1.URL = url;axWindowsMediaPlayer1.Ctlcontrols.play();
}

    针对在线播放功能,我也仿照前面本地播放功能实现了音量控制、暂停播放和下一首:

private async void button2_Click(object sender, EventArgs e)
{if (responseLines.Count > 0){int index = (selectedIndex + 1);if (index >= responseLines.Count()){index = 0;}string playUrl = await GetPlayUrlAsync(index); // 调用获取播放链接的异步方法PlayAudio(playUrl); selectedIndex = index;listBox1.SelectedIndex = index - 1;}
}private void trackBar1_Scroll(object sender, EventArgs e)
{axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
}private void button4_Click(object sender, EventArgs e)
{axWindowsMediaPlayer1.Ctlcontrols.stop(); // 停止播放
}

这里其实应该要像本地播放那样针对不同格式的音乐进行不同的处理,但是我这个API返回的好像是只有MP4格式,就让我偷个懒吧~

7. 设计难点分析

    本次作业中我认为最难的应该是那个异步处理部分和文件下载部分,网络连接可以通过文档一步步调整,但是这个异步处理的思路,我最开始是没有想到的,后来还是问了ChatGPT才解决的,文件下载我最开始以为是直接可以一步到位下载到文件(因为我在网页中打开链接的时候是直接下载的),忽略了缓冲区,老是爆各种各样的错误。

8. 完整代码地址

    C#实现音乐在线播放和下载——Windows程序设计作业3

9. 总结&改进思路

    这次的项目设计本地的音乐播放和在线音乐的搜索、选择、下载和播放功能,总体上是一个较为完整的项目了。
    尽管目前的功能已经能够满足基本的需求,但仍有许多改进和优化的空间。以下是一些可能的改进思路:
    1) 增强用户体验:可以在搜索结果的基础上,增加分页、排序、过滤功能。
    2) 提高代码可维护性:可以引入MVVM模式将业务和UI逻辑分离,提升代码的可读性。
    3) 拓展功能:可以拓展用户功能,用户可以个性化搜索和收藏歌单,与其他人分享自己存在本地的歌单。
    期待未来能够再次更新此项目,实现更多的功能~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/357205.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BookSim2 安装步骤教程 Network-on-Chips (NoCs) 片上网络模拟器 含视频

BookSim简介 BookSim2 一个用于Network-on-Chips (NoCs) 芯片上网络的周期精确模拟器。该模拟器的设计是为了实现网络组件的模拟灵活性和精确建模。 BookSim1 是一个通用的网络模拟器&#xff0c;并不专门针对片上环境。不支持在片上网络环境中提出的一些更先进的功能和拓扑…

网络通信架构

BS架构/CS架构 使用协议分别对应&#xff1a; TCP / HTTP 在计算机网络和软件开发中&#xff0c;CS架构&#xff08;Client-Server Architecture&#xff0c;客户端-服务器架构&#xff09;和BS架构&#xff08;Browser-Server Architecture&#xff0c;浏览器-服务器架构&am…

03-ES6新语法

1. ES6 函数 1.1 函数参数的扩展 1.1.1 默认参数 function fun(name,age17){console.log(name","age); } fn("张美丽",18); // "张美丽",18 fn("张美丽",""); // "张美丽" fn("张美丽"); // &…

直流电机三级串电阻启动

直流电动机在工农业生产中拥有广泛的应用&#xff0c;这主要得益于其调速范围广、调速平稳、过载能力强以及启动和制动转矩大的优点。为了降低起动电流和起动转矩&#xff0c;研究者们探索了直流电动机串电阻起动方法。这种方法通过在直流电动机电枢绕组中串入电阻&#xff0c;…

【软件设计】详细设计说明书(word原件,项目直接套用)

软件详细设计说明书 1.系统总体设计 2.性能设计 3.系统功能模块详细设计 4.数据库设计 5.接口设计 6.系统出错处理设计 7.系统处理规定 软件全套资料&#xff1a;本文末个人名片直接获取或者进主页。

第二十一章 访问者模式

目录 1 访问者模式介绍 2 访问者模式原理 3 访问者模式实现 4 访问者模式总结 1 访问者模式介绍 访问者模式(Visitor Pattern) 的原始定义是&#xff1a;允许在运行时将一个或多个操作应用于一组对象&#xff0c;将操作与对象结构分离 2 访问者模式原理 抽象访问者&#xf…

深入讲解C++基础知识(一)

目录 一、基本内置类型1. 类型的作用2. 分类3. 整型3.1 内存描述及查询3.2 布尔类型 —— bool3.3 字符类型 —— char3.4 其他整型 4. 有符号类型和无符号类型5. 浮点型6. 如何选择类型7. 类型转换7.1 自动类型转换7.2 强制类型转换7.3 类型转换总结 8. 类型溢出8.1 注意事项 …

YOLOv9基础 | 实时目标检测新SOTA,手把手带你深度解析yolov9论文!

前言:Hello大家好,我是小哥谈。YOLOv9是Chien-Yao Wang等人提出的YOLO系列的最新版本之一(截止到目前,YOLOv10已发布),于2024年2月21日发布。它是 YOLOv7的改进版本,两者均由Chien-Yao Wang及其同事开发。本节课就以YOLOv9论文为基础带大家深入解析YOLOv9算法。🌈 …

UE4引擎支持HTML5

文章目录 目的UE版本html5版本编译HTML5小结目的 本篇文章主要写下UE4如何编译支持HTML5,至于为什么是UE4而不是UE5,或者一些其他的话题,本篇不做讨论。 UE版本 先来看看UE的版本管理,如下图:有大概70个分支,有些还在维护,有些还在升级;tags有200多个,很可能还会增…

[Redis]持久化机制

众所周知&#xff0c;Redis是内存数据库&#xff0c;也就是把数据存在内存上&#xff0c;读写速度很快&#xff0c;但是&#xff0c;内存的数据容易丢失&#xff0c;为了数据的持久性&#xff0c;还得把数据存储到硬盘上 也就是说&#xff0c;内存有一份数据&#xff0c;硬盘也…

Linux驱动开发笔记(十三)Sysfs文件系统

文章目录 前言一、Sysfs1.1 Sysfs的引入1.2 Sysfs的目录结构1.2 Sysfs的目录详解1.2.1 devices1.2.2 bus1.2.3 class1.2.4 devices、bus、class目录之间的关系1.2.5 其他子目录 二、Sysfs使用2.1 核心数据结构2.2 相关函数2.2.1 kobject_create_and_add2.2.2 kobject_put()2.2.…

AIGC时代的英语教育:人工智能会取代英语老师吗?

在当前AIGC&#xff08;Artificial Intelligence Generated Content&#xff09;时代&#xff0c;人工智能技术正在迅速发展并渗透到各个领域&#xff0c;其中包括英语教育。面对这一趋势&#xff0c;许多人担心人工智能会取代传统的英语教师。然而&#xff0c;本文将探讨人工智…

RocketMQ源码学习笔记:Broker启动流程

这是本人学习的总结&#xff0c;主要学习资料如下 马士兵教育rocketMq官方文档 目录 1、Broker启动流程2、一些重要的类2.1、MappedFile2.2、MessgeStore2.3、MessageStore的加载启动流程 3、技术亮点3.1、 内存映射3.1.1、简介3.1.2、源码 1、Broker启动流程 Broker启动流程…

Python数据容器

容器定义列表 list定义下标索引列表的方法查询指定元素的下标 index(元素)修改指定下标的元素值插入元素 insert(index,元素)追加一个元素 append(元素)追加一批元素 extend(容器)删除指定下标的元素删除指定元素的第一次出现 remove(元素)清空列表 clear()统计列表中指定元素的…

SD-WAN组网如何帮助企业降低网络成本?

企业在构建IT网络时&#xff0c;常常面临节省费用和提升效益的挑战。IT开销主要包括设备、网络和维护成本。利用OgCloud的SD-WAN组网方案&#xff0c;企业可以有效地应对这些问题。 企业专线网络的高成本问题 企业专线的费用较高&#xff0c;而且数据不能同时在多条专线上传输。…

[FreeRTOS 功能应用] 互斥访问与回环队列 功能应用

文章目录 一、基础知识点二、代码讲解三、结果演示四、代码下载 一、基础知识点 [FreeRTOS 基础知识] 互斥访问与回环队列 概念 [FreeRTOS 内部实现] 互斥访问与回环队列 [FreeRTOS 内部实现] 创建任务 xTaskCreate函数解析 本实验是基于STM32F103开发移植FreeRTOS实时操作系…

“论微服务架构及其应用”写作框架,软考高级,系统架构设计师

论文真题 论微服务架构及其应用近年来&#xff0c;随着互联网行业的迅猛发展&#xff0c;公司或组织业务的不断扩张&#xff0c;需求的快速变化以及用户量的不断增加&#xff0c;传统的单块&#xff08;Monolithic&#xff09;软件架构面临着越来越多的挑战&#xff0c;已逐渐…

关于DrawTools的分析- 一个优秀的C#开源绘图软件

国外大佬&#xff0c;曾经写过两个关于DrawTools相关的开源绘图软件。 我更新了一个优化的版本如下图&#xff0c;稍后会发布更新给大家。 需要的用户可发邮件给我 448283544qq.com 应用于AGV地图编辑器如下&#xff1a; 那么这个优于很多普通的画布软件&#xff0c;包含点、…

STM32项目分享:家庭环境监测系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 1.PCB图 2.PCB板打样焊接图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片&#xff1a; 哔哩哔哩视频链接&#xff1a; https://www.bilibili.…

系统架构师概述

引言 系统架构设计师是项目开发活动中的众多角色之一&#xff0c;它可以是一个小组或者一个人或者是一个团队&#xff0c;架构师包含建筑师&#xff0c;设计师&#xff0c;创造者&#xff0c;缔造者&#xff0c;可以说架构师就是我们社会各个领域的创造者和缔造者。从组织上划分…