5

我的 MVC 控制器中有几个操作,它们通过将 blob 流传递到 FileResult 来返回 Azure blob。像这样:

    public FileResult DownloadReport(string Id)
    {
        // Look up model
        string fileName = messenger.ReportTitle(Id);

        // Get a reference to the blob
        CloudBlockBlob mainReportBlob = cloudBlobContainer.GetBlockBlobReference(Id);

        // Return as a FileResult
        using (var reportReader = mainReportBlob.OpenRead())
        {
            return File(reportReader , "application/pdf", fileName );
        }
    }

我最近将我的 Azure 存储库更新到了最新版本,并开始收到以下异常:

System.NullReferenceException 未被用户代码处理
HResult=-2147467261
消息=对象引用未设置为对象的实例。
Source=Microsoft.WindowsAzure.Storage
StackTrace:
在 Microsoft.WindowsAzure.Storage.Blob.BlobReadStreamBase.ConsumeBuffer(Byte[] buffer, Int32 offset, Int32 count) 在 e:\projects\azure-sdk-for-net\microsoft-azure -api\Services\Storage\Lib\Common\Blob\BlobReadStreamBase.cs:
e:\projects\azure 中 Microsoft.WindowsAzure.Storage.Blob.BlobReadStream.Read(Byte[] 缓冲区,Int32 偏移量,Int32 计数的第 222 行-sdk-for-net\microsoft-azure-api\Services\Storage\Lib\DotNetCommon\Blob\BlobReadStream.cs:
System.Web.Mvc.FileStreamResult.WriteFile 的第 72 行(HttpResponseBase 响应)
在 System.Web.Mvc.FileResult.ExecuteResult(ControllerContext context)
在 System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
在 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList 1 过滤器, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) 1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList

该错误似乎来自 Azure 库本身。有任何想法吗?

4

1 回答 1

7

因此,在使用反编译器逐步完成之后,我发现该BlobReadStreamBase.Dispose()方法在被读取之前就被调用了。进一步挖掘,似乎File()从控制器返回实际上并没有读取流,而只是将其传递给 MVC 的其余部分来处理它。

这意味着我的using()块在 MVC 可以在管道中进一步读取它之前关闭 Blob 流。我将我的操作更改为:

    public FileResult DownloadReport(string Id)
    {
        // Look up model
        string fileName = messenger.ReportTitle(Id);

        // Get a reference to the blob
        CloudBlockBlob mainReportBlob = cloudBlobContainer.GetBlockBlobReference(Id);

        // Return as a FileResult, DON'T place in a using() block or it will be closed early
        var reportReader = mainReportBlob.OpenRead();
        return File(reportReader , "application/pdf", fileName );
    }

这行得通。此外,我在我的反编译器中设置了一个断点,并且稍后会调用 BlobReadStreamBase.Dispose(),因此可能 MVC 正在进一步清理管道。

我不确定为什么这以前有效,因为它不应该。也许是在 Azure 库中修复的错误?

于 2013-11-07T18:47:20.750 回答