我可以创建一个简单地返回图像资产的控制器吗?

我想通过控制器路由这个逻辑,每当请求如下URL时:

www.mywebsite.com/resource/image/topbanner

控制器将查找topbanner.png并将图像直接发送回客户端。

我见过这样的例子,你必须创建一个视图-我不想使用视图。我想只用控制器来做。

这可能吗?


当前回答

您可以直接写入响应,但这样它就不可测试了。最好返回一个延迟执行的ActionResult。这是我的可重用StreamResult:

public class StreamResult : ViewResult
{
    public Stream Stream { get; set; }
    public string ContentType { get; set; }
    public string ETag { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = ContentType;
        if (ETag != null) context.HttpContext.Response.AddHeader("ETag", ETag);
        const int size = 4096;
        byte[] bytes = new byte[size];
        int numBytes;
        while ((numBytes = Stream.Read(bytes, 0, size)) > 0)
            context.HttpContext.Response.OutputStream.Write(bytes, 0, numBytes);
    }
}

其他回答

使用MVC的发布版本,下面是我所做的:

[AcceptVerbs(HttpVerbs.Get)]
[OutputCache(CacheProfile = "CustomerImages")]
public FileResult Show(int customerId, string imageName)
{
    var path = string.Concat(ConfigData.ImagesDirectory, customerId, "\\", imageName);
    return new FileStreamResult(new FileStream(path, FileMode.Open), "image/jpeg");
}

显然,我在这里有一些关于路径构造的应用程序特定的东西,但返回FileStreamResult很好,很简单。

我做了一些性能测试,针对您每天对图像的调用(绕过控制器),平均值之间的差异仅为3毫秒(控制器的平均值为68ms,非控制器的平均值为65ms)。

我尝试了答案中提到的其他一些方法,性能的影响要大得多……一些解决方案的响应高达非控制器的6倍(其他控制器平均340ms,非控制器65ms)。

从Core 3.2下的字节[],你可以使用:

public ActionResult Img(int? id) {
    MemoryStream ms = new MemoryStream(GetBytes(id));
    return new FileStreamResult(ms, "image/png");
}

您可以直接写入响应,但这样它就不可测试了。最好返回一个延迟执行的ActionResult。这是我的可重用StreamResult:

public class StreamResult : ViewResult
{
    public Stream Stream { get; set; }
    public string ContentType { get; set; }
    public string ETag { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = ContentType;
        if (ETag != null) context.HttpContext.Response.AddHeader("ETag", ETag);
        const int size = 4096;
        byte[] bytes = new byte[size];
        int numBytes;
        while ((numBytes = Stream.Read(bytes, 0, size)) > 0)
            context.HttpContext.Response.OutputStream.Write(bytes, 0, numBytes);
    }
}

更新:有比我原来的答案更好的选择。这在MVC之外工作得很好,但最好坚持使用返回图像内容的内置方法。见赞成投票的答案。

你当然可以。试试下面这些步骤:

将映像从磁盘加载到字节数组中 缓存图像,如果您希望对图像有更多的请求,并且不需要磁盘I/O(我的示例在下面没有缓存它) 通过响应改变mime类型。ContentType 响应。写出图像字节数组

下面是一些示例代码:

string pathToFile = @"C:\Documents and Settings\some_path.jpg";
byte[] imageData = File.ReadAllBytes(pathToFile);
Response.ContentType = "image/jpg";
Response.BinaryWrite(imageData);

希望有帮助!

你可以使用HttpContext。响应并直接将内容写入它(WriteFile()可能为您工作),然后从您的动作返回ContentResult而不是ActionResult。

免责声明:我没有尝试过这个,这是基于查看可用的api。: -)