【发布时间】:2021-08-26 19:00:24
【问题描述】:
在过去的几周里,我一直在研究一个 ASP.NET WebAPI,该 API 旨在从公司的一台服务器流式传输视频,并在 HTML5 <video> 元素上播放它。在a guide on C# Corner 之后,我们发布了 API,现在当我们的一个视频的链接粘贴到浏览器中时,它开始下载(顺便说一句,我不确定它是否应该这样做我们正在尝试做的是流)。
我们需要流式传输的文件是mp4,并且将主要通过 Safari 在 iOS 设备上使用。在有人问之前:srcVid 已编程并确认能够成功编码 .mp4 文件,因为我们已经成功地将视频硬编码到这个元素中,没有任何问题。话虽如此,这就是页面处理其 HTML5 元素的方式:
<video autoplay muted id="trainVid" style="width: 75%; height: auto;" controls>
<source id="srcVid" runat="server"
type='video/mp4; codecs*="avc1.424085, mp4a.40.2"' />
</video>
在 API 方面,以下是视频的处理方式,主要遵循 C# 文章设置的示例,以及来自 Stephen Cleary article 的一些帮助:
public class VidService
{
public async void WriteVidBytes(Stream outputStream,
HttpContent content, TransportContext tc)
{
try
{
var filePath = "\\\\server\\link\\to\\file.mp4";
int bufferSize = 1000;
byte[] buffer = new byte[bufferSize];
using (var fileStream = new FileStream(
filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
int fileSize = (int)fileStream.Length;
while (fileSize > 0)
{
int cnt = fileSize > bufferSize ? bufferSize : fileSize,
readBufferSize = fileStream.Read(buffer, 0, cnt);
await outputStream.WriteAsync(buffer, 0, readBufferSize);
fileSize -= readBufferSize;
}
}
}
catch (HttpException ex) { return; }
finally { outputStream.Close(); }
}
public HttpResponseMessage GetVidContent()
{
// NOTE: please see the Edit on 6/10
var httpResponse = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new PushStreamContent(
(Action<Stream, HttpContent, TransportContext>)WriteVidBytes
)
};
return httpResponse;
}
}
public class VidController : ApiController
{
private static readonly VidService vs = new VidService();
[HttpGet]
public HttpResponseMessage GetVid(int id)
{
return vs.GetVidContent(id);
}
}
*请注意,实际程序通过 Video.cs 对象动态获取视频链接
终于在 C# 方面:
protected void LoadVideo(int vidId)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
string.Format("http://mobileAPI.website.com/Vid/GetVid/" + vidId.ToString()));
req.Method = "GET";
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
string jsonString;
using (Stream stream = resp.GetResponseStream())
{
StreamReader r = new StreamReader(stream, System.Text.Encoding.UTF8);
jsonString = r.ReadToEnd();
}
srcVid.Src = jsonString;
}
打开页面时,LoadVideo() 似乎执行没有错误——但在此之后,页面变为空白并永远挂起。我在想这可能是因为我在srcVid.Src 中输入了错误的值,但是如果我不输入 jsonString,那么 do 我为源输入了什么? p>
一如既往,我们将不胜感激任何帮助!如果我遗漏了任何明显的内容,请告诉我,因为这是我第一次使用 WebAPI。
更新 1 (6/10)
我做了一个次要的方法,把WriteVidBytes变成Task——除了变成Task,里面的代码完全一样。另一个区别也是GetVidContent 获取数据的方式:
public HttpResponseMessage GetVidContent(int vId)
{
var httpResponse = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new PushStreamContent(async
(outputStream, httpContext, transportContext) =>
{
await WriteVidTask(outputStream, httpContext, transportContext);
}),
};
return httpResponse;
}
但是,即使通过 Postman 或 Fiddler 获取文件没有问题,页面仍然挂起。
【问题讨论】:
-
从
async void中删除async,并将await替换为同步的output.Write -
@user1344783 我会试试看,但这是个好主意吗?我从未听说过有人同步流式传输视频。编辑:无论如何这会产生相同的结果
-
PushStreamContent 也有一个构造函数,它接受一个真正的异步 lambda:docs.microsoft.com/en-us/previous-versions/aspnet/…,因此您可以将您的
async void转换为async Task并删除演员(Action<Stream, HttpContent, TransportContext>) -
@user1344783 我刚刚更新了问题
-
我仍然认为你应该使用 async Task 而不是 async void ????
标签: c# asp.net asynchronous asp.net-web-api html5-video