Миниатюры на сервере - в GDI + произошла общая ошибка - PullRequest
1 голос
/ 08 мая 2019

Мы уже давно сталкиваемся с этой проблемой и перепробовали множество различных исправлений из сети.Пока ничего не получалось.

Проблема: базовое изображение сохраняется очень хорошо, эскизы не сохраняются.Перед решением, приведенным ниже, я попытался создать отдельные потоки для всех изображений (базовое изображение, 600x600 и 300x300 большого пальца), но это тоже не сработало.Все потоки были созданы из одного байтового массива.Имейте это в виду: это прекрасно работает в среде разработки, среде тестирования и среде Test2, но не работает в среде производства.Я проверил все настройки / переменные среды / разрешения для папок, и все настроено так же, как в тестовых средах.

Пути идут следующим образом:

  • Базовый путь: "~ / images / imageUpl /"
  • Миниатюра Добавить.Путь: «thumbM /»
  • Миниатюра Добавить.Путь: «thumbS /»
  • Структура имени изображения: «X_YYYYMMDD_HHMMSS_XX.png»

Все пути правильные - как это работает в средах Dev / Test / Test2.

Любая помощь по этому вопросу высоко ценится!

РЕДАКТИРОВАТЬ: Что мы пытались до сих пор:

  • Установка разрешений для сети и IISUser
  • Использованиеотдельные потоки для каждого изображения, построенные из исходных данных
  • Добавление thread.sleep (30+), как в других примерах
  • Создание нового растрового изображения из измененного размера и сохранение этого
  • Другой путь для проверки, является ли проблема с его каталогом при производстве

РЕДАКТИРОВАТЬ 2: Для справки, это веб-приложение ASP.NET MVC5, работающее на .NET Framework 4.7.2.

Класс обработки изображений

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Drawing.Drawing2D;
using Newtonsoft.Json;
using System.Threading;

namespace CMS_MVC.Classes
{
    public class ImageProcessor : IDisposable
    {
        public enum PathType : int
        {
            Relative = 1,
            Static = 2
        }

        private Stream _ImageStream { get; set; }
        private HttpContext _Context { get; set; }
        public Image BaseImage { get; set; }
        private int _instanceId { get; set; }

        public ImageProcessor(int instanceId, Stream imageStream, HttpContext context)
        {
            this._ImageStream = imageStream;
            this._Context = context;
            this._instanceId = instanceId;

            this.BaseImage = Image.FromStream(this._ImageStream);
        }

        public ImageProcessor(int instanceId, byte[] imageByteArray, HttpContext context)
        {
            this._Context = context;
            this._instanceId = instanceId;

            this._ImageStream = new MemoryStream(imageByteArray);
            this.BaseImage = Image.FromStream(this._ImageStream);
        }

        public ImageProcessor(int instanceId, string imagePath, PathType pathType, HttpContext context)
        {
            this._Context = context;
            this._instanceId = instanceId;

            if (pathType == PathType.Relative)
            {
                this._ImageStream = new MemoryStream(File.ReadAllBytes(this._Context.Server.MapPath(imagePath)));
                this.BaseImage = Image.FromStream(this._ImageStream);
            }
            else
            {
                this._ImageStream = new MemoryStream(File.ReadAllBytes(imagePath));
                this.BaseImage = Image.FromStream(this._ImageStream);
            }
        }

        public Dictionary<string, bool> SaveImages(string baseImageSavePath, string imageName, Dictionary<string, Tuple<int, int>> thumbnails = null)
        {
            Dictionary<string, bool> results = new Dictionary<string, bool>();
            string lastResult = "main";
            results.Add(lastResult, true);

            try
            {
                this.BaseImage.Save(this._Context.Server.MapPath(Path.Combine(baseImageSavePath, imageName)), ImageFormat.Png);

                if (thumbnails != null)
                {
                    foreach (var thumbnail in thumbnails)
                    {
                        lastResult = thumbnail.Value.Item1.ToString() + "_" + thumbnail.Value.Item2.ToString();
                        results.Add(lastResult, true);

                        using (Bitmap thumbBitmap = this.ResizeImage(thumbnail.Value.Item1, thumbnail.Value.Item2))
                        {
                            Thread.Sleep(50);
                            thumbBitmap.Save(this._Context.Server.MapPath(Path.Combine(baseImageSavePath + thumbnail.Key, imageName)), ImageFormat.Png);
                            Thread.Sleep(50);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                results[lastResult] = false;

                // Log event
            }

            return results;
        }

        private Bitmap ResizeImage(int targetWidth, int targetHeight)
        {
            Tuple<int, int> destSize = this.CalculateThumbnailSizeAspectRatio(targetWidth, targetHeight);

            var destRect = new Rectangle(0, 0, destSize.Item1, destSize.Item2);
            var destImage = new Bitmap(destSize.Item1, destSize.Item2);

            destImage.SetResolution(this.BaseImage.HorizontalResolution, this.BaseImage.VerticalResolution);

            using (var graphics = Graphics.FromImage(destImage))
            {
                graphics.CompositingMode = CompositingMode.SourceCopy;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

                using (var wrapMode = new ImageAttributes())
                {
                    wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                    graphics.DrawImage(this.BaseImage, destRect, 0, 0, this.BaseImage.Width, this.BaseImage.Height, GraphicsUnit.Pixel, wrapMode);
                }
            }

            return destImage;
        }

        private Tuple<int, int> CalculateThumbnailSizeAspectRatio(int targetWidth, int targetHeight)
        {
            // Resize calculations
        }

        public void Dispose()
        {
            if (this._ImageStream != null) this._ImageStream.Dispose();
            if (this.BaseImage != null) this.BaseImage.Dispose();
        }
    }
}

1 Ответ

2 голосов
/ 08 мая 2019

Из документации сайта:

Классы в пространстве имен System.Drawing не поддерживаются для использования в службе Windows или ASP.NET. Попытка использовать эти классы из одного из этих типов приложений может привести к непредвиденным проблемам, таким как снижение производительности службы и исключения во время выполнения.

Затем этот сайт направляет вас в WIC, но это не очень хорошая идея. Классы WPF Media также не поддерживаются на сервере (но столь же четкое утверждение об этом отсутствует).

Были предложены различные альтернативы, вот более старый вопрос SO .

Ваш лучший выбор - искать полностью управляемое решение, о. ImageSharp.

Я все еще ищу подобное утверждение или представление о System.Drawing.Common, базовой библиотеке .net.

...