简体   繁体   English

当UploadFromStream到Azure blob时,最大请求长度超出了异常

[英]Maximum request length exceeded exception when UploadFromStream to Azure blobs

I write an API, trying to upload the HTTP post content(I'm trying to upload a video) to Azure blobs through Stream in c#. 我编写了一个API,尝试通过c#中的Stream将HTTP帖子内容(我正在尝试上传视频)上传到Azure blob。 Some thing like this: 有点像这样:

Stream videoStream = await Request.Content.ReadAsStreamAsync();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);
blockBlob.UploadFromStream(videoStream);

It works OK in my local environment. 它在我的本地环境中正常工作。 But when I deploy this web service to Azure and call the API, I got a "Maximum request length exceeded" exception like this: 但是当我将此Web服务部署到Azure并调用API时,我得到了“超出最大请求长度”异常,如下所示:

System.Web.HttpException (0x80004005): Maximum request length exceeded.           
at System.Web.HttpBufferlessInputStream.ValidateRequestEntityLength()
at System.Web.HttpBufferlessInputStream.GetPreloadedContent(Byte[] buffer, Int32& offset, Int32& count)
at System.Web.HttpBufferlessInputStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at Microsoft.Owin.Host.SystemWeb.CallStreams.DelegatingStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.Web.Http.NonOwnedStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.Net.Http.DelegatingStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at Microsoft.WindowsAzure.Storage.Core.Util.StreamExtensions.WriteToSync[T](Stream stream, Stream toStream, Nullable`1 copyLength, Nullable`1 maxLength, Boolean calculateMd5, Boolean syncRead, ExecutionState`1 executionState, StreamDescriptor streamCopyState)
at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamHelper(Stream source, Nullable`1 length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStream(Stream source, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)

I've changed my Web.config according to some tutorials on web, 我根据web上的一些教程改变了我的Web.config,

<system.web>
  <httpRuntime targetFramework="4.5" maxRequestLength="600000" executionTimeout="3600" />
  <compilation debug="true" targetFramework="4.5" />
</system.web>

<system.webServer>
  <security>
    <requestFiltering>
      <requestLimits maxAllowedContentLength="600000000" />
    </requestFiltering>
  </security>
</system.webServer>

And the API works correctly on my local machine, even with some large videos(larger than 10MB). API可以在我的本地计算机上正常运行,即使是一些大型视频(大于10MB)也是如此。 But it doesn't work as soon as I deploy in Azure Web Service. 但是,只要我在Azure Web Service中部署,它就无法正常工作。 Why is that? 这是为什么?

Update: I used some other methods, tring to bypass the problem. 更新:我使用了一些其他方法,以避免问题。 Such as I tried copy the HTTP request content to a FileStream, and upload the FileStream to Azure blob. 比如我尝试将HTTP请求内容复制到FileStream,并将FileStream上传到Azure blob。 The code like that: 这样的代码:

using (Stream output = File.OpenWrite(TmpFile))
{
    await Request.Content.CopyToAsync(output);
}

CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);

using (var fileStream = System.IO.File.OpenRead(TmpFile))
{
    blockBlob.UploadFromStream(fileStream);
}

But the same exception "Maximum request length exceeded" throw at function CopyToAsync. 但是同样的异常“超出最大请求长度”抛出函数CopyToAsync。

System.Web.HttpException (0x80004005): Maximum request length exceeded.
at System.Web.HttpBufferlessInputStream.ValidateRequestEntityLength()
at System.Web.HttpBufferlessInputStream.GetPreloadedContent(Byte[] buffer, Int32& offset, Int32& count)
at System.Web.HttpBufferlessInputStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state)
at Microsoft.Owin.Host.SystemWeb.CallStreams.DelegatingStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state)
at System.Web.Http.NonOwnedStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state)
at System.Net.Http.StreamToStreamCopy.StartRead()

CHANGES ARE TO THE Web.Config FILE. 更改为Web.Config文件。

The above solution work's I thought I would just add the code changes necessary instead of needing to download the solution and search through it to find what changes are necessary. 上面的解决方案工作我认为我只需要添加必要的代码更改,而不是需要下载解决方案并搜索它以找到必要的更改。 Add the following between the system.web tabs which should already exist with other information between them. 在system.web选项卡之间添加以下内容,这些选项卡应该已存在,并且它们之间存在其他信息

<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" maxRequestLength="600000" executionTimeout="3600" />
</system.web>

Then add the following between the system.webserver tabs which should already exist with other information between them. 然后在system.webserver选项卡之间添加以下内容,这些选项卡应该已存在,并且它们之间存在其他信息。

<system.webserver>
<security>
  <requestFiltering>
    <requestLimits maxAllowedContentLength="600000000" />
  </requestFiltering>
</security>

After that I sent a 12.5 mb .zip file as a blob to azure file storage. 之后,我将一个12.5 MB的.zip文件作为blob发送到azure文件存储。 Using the code provided by Azure. 使用Azure提供的代码。

 // Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
    CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("mycontainer");

// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference("myblob");

// Create or overwrite the "myblob" blob with contents from a local file.
using (var fileStream = System.IO.File.OpenRead(@"path\myfile"))
{
    blockBlob.UploadFromStream(fileStream);
}  

I hope this helps someone. 我希望这可以帮助别人。

Here's a sample that uploads a random 20MB byte array from a console client to a Web API controller, which streams the HTTP request content into Azure blob storage: 下面是一个示例,它将一个随机的20MB字节数组从控制台客户端上传到Web API控制器,该控制器将HTTP请求内容流式传输到Azure blob存储中:

sample 样品

Note that it buffers on the client side (builds the entire 20MB byte array in memory), but it does not buffer on the server. 请注意,它在客户端缓冲(在内存中构建整个20MB字节数组),但它不在服务器上缓冲。

I tested this successfully with the client running on my laptop, and the server running both locally and in an Azure Web App (no extra config, just published the Web API project into the Azure web app). 我在笔记本电脑上运行的客户端成功测试了这个,并且服务器在本地和Azure Web App中运行(没有额外的配置,只是将Web API项目发布到Azure Web应用程序中)。

Hope this helps... best of luck! 希望这有助于......祝您好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM