MVC - 如何从主页面上的文件夹中放置随机图像

时间:2009-04-10 10:01:30

标签: asp.net-mvc

我有一个MVC应用程序,我希望在母版页的顶部 从文件夹中获得一系列随机图像。

要做到这一点,我必须编写代码,但不是在哪里编写代码? 它必须在一个地方完成。

我可能只是在会话开始时设置图像 所以它们被浏览器缓存并提高了网站的性能。

马尔科姆

4 个答案:

答案 0 :(得分:3)

缓存是关键

正如其他人所说,你必须使用缓存,因为你对不经常变化的数据执行重复的磁盘I / O.

我的示例创建并缓存了每个后续请求所需的List<T>图像文件路径。 System.Web.Caching是完美的,因为您可以直接在图像目录上创建CacheDependency对象 - 如果文件被更改或添加,您的缓存将自动失效。然后在下次请求时重新创建它。

使用HashSet<T>

避免重复

我打赌你不希望你头上出现两张相同的照片!

使用Random.Next进行随机化并不排除以前生成的重复项。我使用HashSet<T>作为穷人的独特随机函数,因为HashSet<T>只允许您添加唯一值。

模型

此操作应该是MVC中模型的一部分。您可以根据需要将其更改为与其他数据提取类一起使用。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Caching;

public class RandomImage
{
    public static string[] GetImages(string folder, int count)
    {
        HttpContext context = HttpContext.Current;
        string virtualFolderPath = string.Format("/content/{0}/", folder);
        string absoluteFolderPath = context.Server.MapPath(virtualFolderPath);

        Cache cache = context.Cache;
        var images = cache[folder + "_images"] as List<string>;

        // cache string array if it does not exist
        if (images == null)
        {
            var di = new DirectoryInfo(absoluteFolderPath);
            images = (from fi in di.GetFiles()
                            where fi.Extension.ToLower() == ".jpg" || fi.Extension.ToLower() == ".gif"
                            select string.Format("{0}{1}", virtualFolderPath, fi.Name))
                            .ToList();


            // create cach dependency on image randomFolderName
            cache.Insert(folder + "_images", images, new CacheDependency(absoluteFolderPath));
        }

        Random random = new Random();
        var imageSet = new HashSet<string>();
        if (count > images.Count())
        {
            throw new ArgumentOutOfRangeException("count");
        }

        while (imageSet.Count() < count)
        {
            //using an hashset will ensure a random set with unique values.
            imageSet.Add(images[random.Next(count)]);
        }

        return imageSet.ToArray();
    }
}

控制器

在控制器中访问类似....的方法

string[] images = Models.RandomImage.GetImages("myPictures", 4);

答案 1 :(得分:2)

编写一个帮助函数,该函数将从应用程序启动时生成的文件名数组中获取随机文件名。

答案 2 :(得分:2)

好吧,获取图片:

string[] get_images(string folder) {
     string[] files = Directory.GetFiles(folder, "*.jpg"/* or whatever */);
     List<string> rand = new List<string>();
     Random r = new Random();
     for ( int i = 0; i < numImages; i++ ) {
         rand.Add(Path.GetFileName(files[r.Next(files.Length-1)]));
     }
     return rand.ToArray();
}

然后在母版页中:

<% PrintImages(); %>

PrintImages()的位置是:

string[] img = get_images(Server.MapPath("~/Content/RandomImages"));
foreach (string i in img) { Response.Write("<img src=\"/Content/RandomImages/"+i+"\" />"); }

这是一个粗略的解决方案,缓存会很好 - 这会真正打破磁盘。

答案 3 :(得分:0)

我想确保在我做任何更复杂的事情之前,每次只读取目录并生成文件名是一个真正的瓶颈。它的效率肯定不高,但代码可以说更简单。如果它不是瓶颈,则负责呈现视图的控制器操作是代码的正确位置。请注意,如果您希望每次都更改图像,则需要关闭操作的输出缓存(如果尚未更改)。

如果事实证明读取文件名并构建链接确实是一个瓶颈 - 它可能比读取实际文件花费的时间少得多 - 并且目录中的文件可以在应用程序运行时更改,然后构建它们的集合并在登录时将它们存储在会话中是一种合理的方法来处理它。需要注意的是,如果应用程序还负责上传图像(以便它知道何时更改),您可以在应用程序启动时加载它们并将它们保存在由应用程序更新的全局实例中,因为图像是上传(或删除)。

收集图像后(通过每次,从会话或全局实例读取),使用随机数生成器选择要显示的图像或要通过使用旋转的集合类似于jQuery Cycle插件,将它(它们)传递给视图并让它渲染图像标签。