我有一个页面,它根据唯一ID返回音乐文件。
e.g。
Source.aspx?id=15 // returns 01_myfile.mp3
Source.aspx?id=37 // returns 02_something.flac
Source.aspx?id=3 // returns 03_anotherone.ogg
我想在html5 <audio> tag
中使用这些来源。我让它在某个时候工作,但我无法在文件中跳过。就在那时我发现了Range
标题并试图实现这一点。
...
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.StatusCode = (Int32) HttpStatusCode.PartialContent;
Response.AddHeader("Accept-Ranges", "bytes");
Response.AddHeader("Content-Disposition", $"inline; filename=\"{file.FullName}\"");
Response.AddHeader("Content-Length", fileLength.ToString()); // e.g. 100
Response.AddHeader("Content-Range", $"{rangeFrom}-{rangeTo - 1}/{fileLength}"); // e.g. 0-99/100
Response.ContentType = GetContentType(file); // e.g. "audio/mpeg"
String contentDuration = t.Duration?.ToString() ?? "360"; // duration of the audio file or some default guess
Response.AddHeader("X-Content-Duration", contentDuration);
Response.AddHeader("Content-Duration", contentDuration);
Response.TransmitFile(file.FullName, rangeFrom, rangeTo - rangeFrom); // transmit requested section
Response.End();
Request URL:...Source.aspx?id=17686
Request Method:GET
Status Code:206 Partial Content
Remote Address:[::1]:51000
Referrer Policy:no-referrer-when-downgrade
Response Headers
view source
Accept-Ranges:bytes
Cache-Control:private
Content-Disposition:inline; filename="Z:\music\...\mymusicfile.mp3"
Content-Duration:360
Content-Length:12683228
Content-Range:0-12683227/12683228
Content-Type:audio/mpeg
Date:Tue, 12 Dec 2017 15:33:23 GMT
Server:Microsoft-IIS/10.0
X-AspNet-Version:4.0.30319
X-Content-Duration:360
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?...?=
Request Headers
view source
Accept:*/*
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:en-US,en;q=0.9
Connection:keep-alive
Cookie:.ASPXAUTH=...
Host:localhost:51000
Range:bytes=0-
Referer:...
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Query String Parameters
view source
view URL encoded
id:17686
因此。我错过了什么?为什么这个版本没有按预期提供文件?
有什么想法吗?谢谢!
答案 0 :(得分:0)
就像我在评论中看到的那样,我在Content-Range
中错过了单位。通过修复此问题,在音频文件中跳过和搜索就像魅力一样。
从......
更改Content-Range
格式
0-99/100
...到......
bytes 0-99/100
注意bytes
部分?这就是单位。
使用正确的状态代码进行响应对于所有功能都能正常工作至关重要。
并不总是包含范围标题。根据此情况,您必须使用不同的HTTP状态代码进行响应。
第一种情况:如果提供了格式错误的范围标题,请回复
416
请求范围 - 不是 - 满意的 HTTP状态代码,没有内容范围等元数据标题,也没有附加文件第二种情况:如果未提供范围标题,请使用
200
确定 HTTP状态代码进行回复, OP中列出的所有元数据头和附加的完整文件内容范围第三种情况:如果提供了
0-
范围标题,也请回复200
确定 HTTP状态代码和附加的完整文件内容范围第4种情况:对于提供的任何其他范围标题,请使用
206
部分内容 HTTP状态代码进行回复和请求的内容范围
private readonly Dictionary<String, String> _mimeTypes =
new Dictionary<String, String> {{".mp3", "audio/mpeg"}, {".wav", "audio/vnd.wav"}}; // all audio mime types i am interessted in which do not follow the "audio/fileextension" format
private void DownloadFile(String path)
{
FileInfo file = new FileInfo(path);
Int64 fileLength = file.Length;
Int64 rangeTo = fileLength;
String rangeHeader = Request.Headers["range"];
String[] parts;
if (rangeHeader != null)
{
rangeHeader = rangeHeader.Replace(" ", "").ToLower().Trim().Replace("bytes=", ""); // comes with the format of "bytes=0-100"
parts = rangeHeader.Split('-').Where(x => !String.IsNullOrWhiteSpace(x)).ToArray(); splits into "0" and "100"
}
else
{
parts = new[] {"0"}; // simulate 0- range, full file will be returned
}
// trying to parse range
Int64 rangeFrom = 0;
switch (parts.Length)
{
case 2:
{
// full range passed (e.g. "100-200")
if (!Int64.TryParse(parts[1], out rangeTo))
{
// cannot parse input to int -> invalid
SendResponseRangeNotSatisfiable();
return;
}
goto case 1;
}
case 1:
// only start provided (e.g. "0-")
if (!Int64.TryParse(parts[0], out rangeFrom))
{
// cannot parse input to int -> invalid
SendResponseRangeNotSatisfiable();
return;
}
goto case 0;
case 0:
{
// no range provided, take default value for full file (e.g. "0-..")
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.StatusCode = rangeFrom == 0 && rangeTo == fileLength
? (Int32) HttpStatusCode.OK
: (Int32) HttpStatusCode.PartialContent;
Response.AddHeader("Accept-Ranges", "bytes");
Response.AddHeader("Content-Disposition", $"inline; filename=\"{file.FullName}\"");
Response.AddHeader("Content-Length", fileLength.ToString());
Response.AddHeader("Content-Range", $"bytes {rangeFrom}-{rangeTo - 1}/{fileLength}");
Response.ContentType = _mimeTypes.ContainsKey(file.Extension)
? _mimeTypes[file.Extension]
: $"audio/{file.Extension.Substring(1)}";
String contentDuration = TheLengthOfYourMusicFileInSeconds;
Response.AddHeader("X-Content-Duration", contentDuration);
Response.AddHeader("Content-Duration", contentDuration);
Response.TransmitFile(file.FullName, rangeFrom, rangeTo - rangeFrom);
Response.Flush();
Response.End();
break;
}
default:
SendResponseRangeNotSatisfiable();
return;
}
}
private void SendResponseRangeNotSatisfiable()
{
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.StatusCode = (Int32) HttpStatusCode.RequestedRangeNotSatisfiable;
Response.Flush();
Response.End();
}