如何在 ASP.NET MVC 上使用 IHttpHandler return 来自 azure 存储帐户的图像

How to return images from azure storage account using IHttpHandler on ASP.NET MVC

我有一个 IHttpHandler 拦截图像请求和响应,如果用户有权通过某些数据库驱动的算法查看图像或不查看图像。 无论如何,在我将图像移至存储帐户之前,代码工作正常。与我从服务器的本地磁盘提供服务的时间相比,现在图像请求需要更多的时间。所以我想知道我是否在我的 IHttpHandler 代码上做错了什么,这就是问题的原因。

我请求像这样的图片:

<img src="/web-thumb/{userid}/{filename}.jpg">

我创建了一个路由定义:

    routes.Add("ThumbnailsRoute",
        new Route("web-thumb/{userid}/{filename}", new ThumbnailRouteHandler()));

这是我的缩略图处理程序:

public class ThumbnailRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new ThumbnailHandler(requestContext);
    }
}        


public class ThumbnailHandler : IHttpHandler
{
    public ThumbnailHandler()
    {
    }

    public ThumbnailHandler(RequestContext requestContext)
    {
        RequestContext = requestContext;
    }

    protected RequestContext RequestContext { get; set; }

    public bool IsReusable
    {
        get { return false; }
    }

    public void ProcessRequest(HttpContext context)
    {
        // find physical path to image here.  

        var binResponse = Utility.GetFileContent("images/" + RequestContext.RouteData.Values["userid"] + "/thumbnail/" + RequestContext.RouteData.Values["filename"]);

        context.Response.BinaryWrite(binResponse);

        context.Response.End();
    }
}

这里是 GetFileContent 辅助静态函数,用于将图像从存储器下载到字节数组:

    public static byte[] GetFileContent(string fileName)
    {
        CloudBlobContainer container = getUserMediaContainer();
        CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
        if (blockBlob.Exists()) { 
            blockBlob.FetchAttributes();
            long fileByteLength = blockBlob.Properties.Length;
            byte[] fileContent = new byte[fileByteLength];
            for (int i = 0; i < fileByteLength; i++)
            {
                fileContent[i] = 0x20;
            }
            blockBlob.DownloadToByteArray(fileContent, 0);
            return fileContent;
        }
        return new byte[0];
    }
    private static CloudBlobContainer getUserMediaContainer()
    {
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(System.Configuration.ConfigurationManager.ConnectionStrings["StorageConn"].ConnectionString);
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

        CloudBlobContainer userMedia = blobClient.GetContainerReference("user-media");
        userMedia.CreateIfNotExists();

        return userMedia;
    }

这是两端35kb图片请求的请求时间明细:

您的 GetFileContent 函数正在创建与存储的连接并在每次调用时检查容器是否存在,我会保留对 CloudStorageAccount 的引用并在您的应用程序启动时检查容器是否存在.我假设没有理由在您的应用程序处于 运行.

时删除容器

例如

public static class Utility
{
    // Keep ref to CloudStorageAccount
    private static CloudStorageAccount _storageAccount;

    private static CloudStorageAccount StorageAccount
    {
        get
        {
            if (_storageAccount == null)
            {
                _storageAccount = CloudStorageAccount.Parse(System.Configuration.ConfigurationManager.ConnectionStrings["StorageConn"].ConnectionString);
            }
            return _storageAccount;
        }
    }

    static Utility()
    {
        // Just check the container exists when app starts or on first download
        CloudBlobClient blobClient = StorageAccount.CreateCloudBlobClient();
        CloudBlobContainer userMedia = blobClient.GetContainerReference("user-media");
        userMedia.CreateIfNotExists();
    }

    public static byte[] GetFileContent(string fileName)
    {
        CloudBlobClient blobClient = StorageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference("user-media");
        CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
        if (blockBlob.Exists())
        {
            blockBlob.FetchAttributes();
            long fileByteLength = blockBlob.Properties.Length;
            byte[] fileContent = new byte[fileByteLength];
            blockBlob.DownloadToByteArray(fileContent, 0);
            return fileContent;
        }
        return new byte[0];
    }
} 

你没有说下载时间的差异有多大,但我假设你不希望从 blob 存储而不是从本地服务器下载而不改变性能。