Получение растрового изображения из кэша - PullRequest
2 голосов
/ 18 октября 2010

Всякий раз, когда я пытаюсь получить растровое изображение, которое я кэшировал из контекста, я получаю исключение аргумента. Растровое изображение создается из кэшированного объекта, но его содержимое повреждено.

Исключение выдается на линии

ImageFormat imageFormat = bitmap.RawFormat;

bitmap.RawFormat 'вызвала исключение типа' System.ArgumentException '

, который просто дает мне сообщение «Параметр недействителен».

Когда я вставляю точку останова в коде, смотрю на растровое изображение, созданное из кэша, все свойства возвращают одно и то же исключение.

Вот запрос процесса от моего обработчика ....

    /// <summary>
    /// Processes the image request.
    /// </summary>
    /// <param name="context">The httpContext handling the request.</param>
    public void ProcessRequest(HttpContext context)
    {
        //write your handler implementation here.
        if (!string.IsNullOrEmpty(context.Request.QueryString["file"]))
        {
            string file = context.Request.QueryString["file"];
            bool thumbnail = Convert.ToBoolean(context.Request.QueryString["thumb"]);
            // Throw in some code to check width and height.
            int width = Convert.ToInt32(context.Request.QueryString["width"]);
            int height = Convert.ToInt32(context.Request.QueryString["height"]);

            // Store our context key.
            string key = file;

            // Strip away our cache data value.
            file = file.Substring(0, file.LastIndexOf("_", StringComparison.OrdinalIgnoreCase));

            OnServing(file);

            try
            {
                //Check the cache for a file.
                Bitmap bitmap = (Bitmap)context.Cache[key];
                if (bitmap != null)
                {
                    ImageFormat imageFormat = bitmap.RawFormat;
                    // We've found something so lets serve that.
                    using (MemoryStream ms = new MemoryStream())
                    {
                        bitmap.Save(ms, imageFormat);
                        context.Response.BinaryWrite(ms.ToArray());
                    }

                }
                else
                {
                    // Nothing found lets create a file.
                    // Lock the file to prevent access errors.
                    lock (this.syncRoot)
                    {
                        string path = HostingEnvironment.MapPath(String.Format("~/Images/{0}", file));
                        FileInfo fi = new FileInfo(path);
                        if (fi.Exists)
                        {
                            using (Bitmap img = (Bitmap)Bitmap.FromFile(path))
                            {
                                ImageFormat imageFormat = img.RawFormat;
                                if (thumbnail)
                                {
                                    ImageEditor imageEditor = new ImageEditor(img);
                                    Size size = new Size(width, height);
                                    imageEditor.Resize(size, true);
                                    imageEditor.FixGifColors();

                                    using (MemoryStream ms = new MemoryStream())
                                    {
                                        imageEditor.Image.Save(ms, imageFormat);

                                        // Add the file to the cache.
                                        context.Cache.Insert(key, img, new System.Web.Caching.CacheDependency(path));
                                        imageEditor.Dispose();
                                        context.Response.BinaryWrite(ms.ToArray());
                                    }
                                }
                                else
                                {
                                    using (MemoryStream ms = new MemoryStream())
                                    {
                                        img.Save(ms, imageFormat);

                                        // Add the file to the cache.
                                        context.Cache.Insert(key, img, new System.Web.Caching.CacheDependency(path));
                                        context.Response.BinaryWrite(ms.ToArray());
                                    }
                                }
                                OnServed(file);
                            }
                        }
                        else
                        {
                            OnBadRequest(file);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
                // OnBadRequest(ex.Message);
                // return a default empty file here.                    
            }

        }

    }

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

3 голосов
/ 18 октября 2010

Я могу рекомендовать не держаться за ресурсы дольше, чем они необходимы.

Что касается приведенного выше кода, проблема в том, что вы не создаете новое растровое изображение при получении сохраненного изображения - вы извлекаете существующее из кэша, который, вероятно, уже удален. Попробуйте вместо этого использовать следующее:

// When saving to the cache, use a MemoryStream to save off the bitmap as an array of bytes
using (MemoryStream ms = new MemoryStream()) {
    bitmap.Save(ms, bitmap.RawFormat);
    context.Cache.Insert(key, (byte[])ms.ToArray(), ...
    ...
}

...

// When retrieving, create a new Bitmap based on the bytes retrieved from the cached array
if (context.Cache[key] != null) {
    using (MemoryStream ms = new MemoryStream((byte[])context.Cache[key])) {
        using (Bitmap bmp = new Bitmap(ms)) {
            bmp.Save(context.Response.OutputStream ...
...
2 голосов
/ 18 октября 2010

Когда вы кэшируете объект изображения, вы делаете это внутри блока using:

using (Bitmap img = (Bitmap)Bitmap.FromFile(path))
{
    // ... lots of code

    // Add the file to the cache.
    context.Cache.Insert(key, img, new System.Web.Caching.CacheDependency(path));

    // ... other code
}

В конце этого блока использования ваше растровое изображение будет удалено. Поэтому вы не можете использовать его снова. Вам нужно прекратить удаление растрового изображения, если вы хотите использовать его снова из кэша.

Однако, учитывая, что вы просто хотите вернуть то же изображение снова, если оно кэшировано, может быть проще и эффективнее просто кэшировать MemoryStream - это не страдает от невидимых связей GDI + и может быть возвращено практически без обработки при попадании в кеш.

...