服务器上的缩略图-GDI +

时间:2019-05-08 08:41:46

标签: c# image bitmap gdi+ gdi

很长一段时间以来,我们一直在解决此问题,并且尝试了许多来自网络的修复程序。到目前为止,没有任何效果。

问题:基本图像保存得很好,保存缩略图失败。在下面的解决方案之前,我曾尝试为所有图像(基本图像,600x600和300x300拇指)创建单独的流,但这也不起作用。所有流都是从相同的字节数组构造的。请记住:在开发环境,测试环境和Test2环境下,此方法工作正常,但是在生产环境下则无法工作。我已经检查了所有设置/环境变量/文件夹的权限,并且所有设置都与测试环境相同。

路径如下:

  • 基本路径:“〜/ images / imageUpl /”
  • 缩略图添加。路径:“ thumbM /”
  • 缩略图添加。路径:“ thumbS /”
  • 图片名称结构:“ X_YYYYMMDD_HHMMSS_XX.png”

所有路径均正确-在Dev / Test / Test2环境下均可使用。

对此有任何帮助,深表感谢!

编辑:到目前为止我们尝试过的事情:

  • 设置网络和IISUser的权限
  • 对使用原始源数据构建的每个图像使用单独的流
  • 按照其他示例添加thread.sleep(30 +)
  • 从调整后的位图创建一个新的位图并保存
  • 用于测试其目录是否在生产中出现问题的不同路径

编辑2:作为参考,这是一个运行.NET Framework 4.7.2的ASP.NET MVC5 Web应用程序。

图像处理器类

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 个答案:

答案 0 :(得分:2)

documentation网站上:

  

System.Drawing命名空间中的类不支持在Windows或ASP.NET服务中使用。尝试从这些应用程序类型之一中使用这些类可能会产生意外问题,例如服务性能下降和运行时异常。

然后该站点将您定向到WIC,但这不是一个好主意。服务器上也不支持WPF Media类(但是缺少与此明确相同的声明)。

各种各样的选择出现了,这里是an older SO question

您最好的选择是寻找一个完全托管的解决方案。 ImageSharp。

我仍在寻找有关{.net核心库System.Drawing.Common的类似陈述或见解。