如何在ASP.NET MVC中动态调整图片大小?

11

问题

如何在ASP.NET MVC中动态调整图片大小?

背景

我试图自动从服务器上的图像创建缩略图。在ASP.NET Webforms中,我创建了一个HTTPHandler来完成此操作,并在web.config中添加了所有图像扩展名的动词以通过处理程序传递。该处理程序很好,因为如果您想要原始图像,则会使用典型的图像标记:

<img src="pic.jpg"/>

但是,如果您想要调整大小的图像,则会使用:

<img src="pic.jpg?width=320&height=240"/>

是否有一种方法在ASP.NET MVC中复制相同的行为?


3
与 HttpHandler 不同的是,HttpModule 能够无缝地在 MVC 和 WebForms 中工作。ASP.NET 最受欢迎的图像调整 HttpModule 是 http://imageresizing.net 。它是免费、开源的,并且非常易用。 - Lilith River
很棒,谢谢。不幸的是,在2009年我提出这个问题时,imageresizing.net还没有出现。 - Daniel T.
其实它是从2007年就开始存在了。但公平地说,直到2009年初它才能进入谷歌搜索结果的第一页... - Lilith River
3个回答

13
使用System.Web.Helpers.WebImage中提供的WebImage类,您可以实现此目的。
您可以使用这个很棒的工具在运行时输出调整大小的图像。
示例代码:
public void GetPhotoThumbnail(int realtyId, int width, int height)
{
    // Loading photos’ info from database for specific Realty...
    var photos = DocumentSession.Query<File>().Where(f => f.RealtyId == realtyId);

    if (photos.Any())
    {
        var photo = photos.First();

        new WebImage(photo.Path)
            .Resize(width, height, false, true) // Resizing the image to 100x100 px on the fly...
            .Crop(1, 1) // Cropping it to remove 1px border at top and left sides (bug in WebImage)
            .Write();
    }

    // Loading a default photo for realties that don't have a Photo
        new WebImage(HostingEnvironment.MapPath(@"~/Content/images/no-photo100x100.png")).Write();
}

在视图中,您可能会看到类似于以下内容的代码:
<img src="@Url.Action("GetPhotoThumbnail",
     new { realtyId = item.Id, width = 100, height = 100 })" />

更多关于此的信息在这里:使用ASP.NET MVC动态调整图像大小

ASP.NET网站上还有一个很好的教程:在ASP.NET Web页面(Razor)站点中使用图像


3

您可以绝对重复使用相同的IHttpHandler。您只需要一个新的IRouteHandler来将传入的请求映射到正确的处理程序:

public class ImageRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new YourImageHttphandler();
    }
}

在你的路由中,添加以下内容:
routes.Add("Images", new Route("images/{*file}", new ImageRouteHandler()));

现在,/images路径下的任何请求(例如/images/pic.jpg?width=320&height=240)都将由现有的处理程序处理。显然,您可以更改路由模式以匹配任何有意义的路径,就像典型的MVC路由一样。

这段代码适用于 images 文件夹下的子目录吗? - Daniel T.
@DanielT 是的!请查看我答案中微小的修改 - 在 {*file} 加上星号将会使该路由匹配 /images 下的所有内容,包括子目录。 - Rex M
嗯,有一个小问题:这个路由只在我手动将URL键入地址栏时才会起作用,像这样:http://localhost:4692/Content/images/IMG_0146.JPG。然而,我需要嵌入视图中的图片,并且它不会通过路由处理程序,因为它已经被路由到控制器了。 - Daniel T.
@DanielT 嗯,不太确定你的意思。页面上的每个资源(例如<img src...)都会被浏览器作为单独的请求发送到服务器,并且每个请求将被单独处理。你能详细描述一下你看到的情况吗? - Rex M
CSS中作为背景图像的图片怎么办? - Ryan

0

在MVC中你也可以做同样的事情。你可以像之前一样使用HttpHandler,或者创建一个流式调整大小图像的Action。

如果是我,我会创建一个带有调整大小方法的控制器。


你能详细说明一下你所说的关于创建一个流传调整大小后的图像的操作吗? - Daniel T.
等等,我想我明白了。你的意思是使用RedirectToAction("Thumbnail")返回一个缩略图,对吗? - Daniel T.
我现在不在电脑前,但是有一个“Content”方法可以流式传输数据。我相信它有一个签名,接受流或字节数组,然后有一个参数表示内容类型。对于内容类型,您需要传递“image/jpg”。然后您只需在HTML图像元素中引用该操作即可。 - Chuck Conway
以上假设您已经将调整大小后的图像作为流或字节数组存储在内存中。 - Chuck Conway
我非常希望视图可以调整图像的大小。我的观点是控制器只应该给视图一个要显示的数据“表”,在这种情况下,是与某个条件匹配的所有图像的列表,并且如果需要的话,由视图来处理图像的调整大小工作。 - Daniel T.
如果你要对一个答案进行负评,最好留下一条评论以示礼貌。对于三年前写的答案进行负评有点荒谬。提供自己的答案可以增加价值。 - Chuck Conway

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接