我正在使用Azure中的Web服务框架以及与Azure进行通信的网站。网站应使用文件名调用Azure,Azure中的Web服务应在blob存储中找到给定的文件,然后将其发送回客户端进行下载。
只要返回的文件很小(使用20mb mp4文件进行测试就可以了),我就可以使它正常工作,但是像1Gb mp4文件这样的东西最终会引发异常。
C#请求代码:
public override async Task ProcessRequestAsync(HttpContext context)
{
JavaScriptSerializer oSearlizer = new JavaScriptSerializer();
object o = new
{
sourceStorageAccountName = "accountName",
sourceStorageAccountKey = "accountKey",
sourceContainer = "test"
};
string req = oSearlizer.Serialize(o);
HttpContent content = new StringContent(req, Encoding.UTF8, "application/json");
HttpClient client = new HttpClient();
HttpResponseMessage x = await client.PostAsync("http://localhost:7071/api/get_file", content);
context.Response.Clear();
context.Response.Buffer = false;
context.Response.BufferOutput = false;
context.Response.ContentType = "video/mp4";
context.Response.AddHeader("content-disposition", "attachment;filename=test.mp4"); // Save file
context.Response.Charset = "";
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.BinaryWrite(await x.Content.ReadAsByteArrayAsync());
context.Response.End();
}
Azure网络服务代码:
CloudBlobContainer sourceBlobContainer = CopyBlobHelpers.GetCloudBlobContainer(_sourceStorageAccountName, _sourceStorageAccountKey, _sourceContainer);
CloudBlockBlob blob = sourceBlobContainer.ListBlobs().First();
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
Stream stream = blob.OpenRead(null, new BlobRequestOptions() { ServerTimeout = new System.TimeSpan(2, 59, 59), MaximumExecutionTime = new System.TimeSpan(2, 59, 59) });
response.Content = new StreamContent(stream);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileNameZip;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("video/mp4");
return response;
就像我说的那样,此代码对于20mb的mp4文件可以正常工作,但对于1Gb或更大的mp4文件则抛出异常。我得到的异常是:“异常:SocketException:现有连接被远程主机强行关闭”
如果我从请求代码中删除“ await”,而使用“ .Result”,则会收到另一个异常:“异常:HttpRequestException:将内容复制到流时出错。”
逐步执行代码,输入“ await client.PostAsync()”,然后逐步执行Azure Web服务代码,直到返回return语句。然后我再次走动,在1-2分钟内没有任何反应,然后引发了异常。
有人对可能发生的事情有任何想法吗?我认为这与流试图推送过多数据或某处超时有关,但是我正在做的事情似乎无法解决此问题。
答案 0 :(得分:1)
我添加并删除了关于使用HttpClient.Timeout
的注释,因为我认为虽然可以解决问题,但您使用的设计存在问题。您正在使用POST请求来获取资源。您确实应该使用GET请求。通常,这种方式的工作方式是您可以调用类似
GET http://localhost:7071/api/{file_name}
其中{file_name}
是您要下载的文件的名称。该服务通常会知道有关存储帐户的信息,因此您不需要当前拥有的请求正文。您可能希望服务与从哪个存储帐户下载无关,但我认为这不太可能。
我还觉得有必要注意,如果您要继续通过网络发送存储帐户信息,则需要使用HTTPS而不是HTTP,因为从现在开始,您正在发送存储帐户密钥以纯文本格式。
答案 1 :(得分:1)
由于如下所示,Azure Functions的默认超时期限受到限制,因此您会遇到问题str2
,该问题是从Azure Functions下载大文件的。请参阅Functions limits。
因此,这些小文件可以在不到超时时间的短时间内下载,但是大文件将在超时后被强制关闭。
解决方案是使用SAS令牌从Azure Function向客户端响应blob url,然后通过sas url从Azure Blob Storage直接下载blob,这是因为sas url无需额外的身份验证并且对Azure存储没有超时限制。
如果您不熟悉如何为Blob生成SAS令牌,则可以参考官方示例代码Getting Started with Shared Access Signatures (SAS)