在 Web 开发中,正确返覆信频和视频流给前端的方式是确保服务器端以流的形式发送媒体文件,而不是将整个文件加载到内存中,然后再传输。这种做法可以进步性能,避免内存溢出,尤其是在处理大文件时。
对于音频和视频流的处理,最常见的技术是 HTTP 流式传输(HTTP Streaming) Range 请求。这些方法允许客户端(欣赏器或播放器)按需请求并接收音频和视频的部分内容,而不是一次性加载整个文件。
要在后端处理包罗 Range 头的请求,起首必要理解 Range 请求头是如何工作的。客户端通过 Range 请求头向服务器指定请求的字节范围。服务器根据 Range 请求返回相应的数据片段,通常用于视频、音频或大文件的流式传输。
1. Range 请求头的工作原理
客户端请求某个文件的部分内容时,会在 HTTP 请求头中包罗 Range,比方:
表示客户端请求文件的第 0 字节到第 1023 字节(共 1024 字节)。
如果客户端想请求多个范围(比方文件的两个不连续部分),则可以使用如下格式:
- Range: bytes=0-1023
- , 2048-3071
复制代码 2. 后端处理 Range 请求头
在 C# 中,后端必要从请求头中获取 Range 的信息,并且根据该信息返回对应的字节范围。通常可以通过 HttpRequest.Headers 来获取请求头中的 Range。
示例代码(ASP.NET Core):
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.AspNetCore.Http;
- using System.IO;
- using System.Linq;
- using System.Net.Http.Headers;
- [Route("api/[controller]")]
- public class MediaController : ControllerBase
- {
- [HttpGet("audio")]
- public IActionResult GetAudio(string filename)
- {
- var fileInfo = new FileInfo(filename);
- if (!fileInfo.Exists)
- {
- return NotFound();
- }
- var fileLength = fileInfo.Length;
- var rangeHeader = Request.Headers["Range"].ToString();
- if (string.IsNullOrEmpty(rangeHeader))
- {
- return BadRequest("Invalid Range header.");
- }
- // 解析 Range 请求头
- var rangeMatch = System.Text.RegularExpressions.Regex.Match(rangeHeader, @"bytes=(\d+)-(\d+)?");
- if (!rangeMatch.Success)
- {
- return BadRequest("Invalid Range header.");
- }
- var start = long.Parse(rangeMatch.Groups[1].Value);
- var end = rangeMatch.Groups[2].Success ? long.Parse(rangeMatch.Groups[2].Value) : fileLength - 1;
- // 确保范围合法
- if (start < 0 || end >= fileLength || start > end)
- {
- return BadRequest("Invalid range.");
- }
- // 读取文件的指定范围
- var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
- var contentRange = new RangeHeaderValue(start, end);
- var contentLength = end - start + 1;
- // 设置响应头
- Response.Headers.Add("Content-Range", $"bytes {start}-{end}/{fileLength}");
- Response.Headers.Add("Accept-Ranges", "bytes");
- Response.StatusCode = StatusCodes.Status206PartialContent; // 206 Partial Content
- fileStream.Seek(start, SeekOrigin.Begin);
- return File(fileStream, "audio/mpeg", enableRangeProcessing: true);
- }
- }
复制代码 解释:
- Range 请求头剖析:
- Request.Headers["Range"] 获取 Range 请求头的内容。
- 使用正则表达式 @"bytes=(\d+)-(\d+)?" 来提取请求的开始和结束字节。
- 如果 end 字段缺失,则将 end 设置为文件的末了一个字节。
- 合法性检查:
- 确保 start 和 end 在合法范围内,即它们不能超出文件的总长度,也不能发生 start > end 的情况。
- 文件流处理:
- 使用 FileStream 打开文件,并设置 Seek 方法从指定的字节位置开始读取文件内容。
- 返回部分文件内容时,设置相应头 Content-Range,告知客户端返回的数据范围。
- 返回部分内容:
- 设置相应状态码为 206 Partial Content,表示这是一个部分内容的相应。
- 使用 File 方法返回文件流,并通过 enableRangeProcessing: true 告诉 ASP.NET Core 进行范围处理。
3. 前端使用 <audio> 标签播放音频
在前端使用 <audio> 标签时,欣赏器会自动发出 Range 请求,只要服务器支持 Range 请求,并且文件能够分段提供。你不必要特殊设置客户端来处理 Range,欣赏器会本身处理。
示例:基础 <audio> 标签用法
- <html>
- <head>
- <title>audio page</title>
- </head>
- <body>
- <audio controls>
- <source src="http://127.0.0.1:9099/api/media/audio?filename=1.mp3" type="audio/mp3">
- </audio>
- </body>
- </html>
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |