简体   繁体   English

上传多张图片后创建缩略图的GDI +错误

[英]GDI+ error upon upload multiple images then create thumbnails

I've got an image upload page that works just fine when I only upload the files. 我有一个图片上传页面,当我仅上传文件时,该页面工作正常。

I added a 'Create Thumbnail' function. 我添加了“创建缩略图”功能。 It looks like the file system has a handle on the images when the thumbnail process starts. 缩略图处理开始时,似乎文件系统在图像上具有句柄。

I get the 'unspecified GDI+ error' only when the image is over about 250K. 仅当图像超过约250K时,我才收到“未指定的GDI +错误”。 When the files are below 250K, thumbnails are created as expected. 当文件小于250K时,将按预期创建缩略图。

What are my options? 我有什么选择? Is there an elegant solution here? 这里有一个优雅的解决方案吗? I want something not hacky. 我想要一些不客气的东西。
Also, I am using HttpFileCollection so we can upload multiple images at one time. 另外,我正在使用HttpFileCollection,因此我们可以一次上传多个图像。 I've tried to use .Dispose on the Thumbnail creation, but it fails before we get to this point. 我尝试在缩略图创建中使用.Dispose,但在此之前它还是失败了。

public void Upload_Click(object Sender, EventArgs e)
{
 string directory = Server.MapPath(@"~\images\");
  HttpFileCollection hfc = Request.Files;
  for (int i = 0; i < hfc.Count; i++)
  {
    HttpPostedFile hpf = hfc[i];

    if (hpf.ContentLength > 0)
    {
      string fileName = hpf.FileName;
      fileName = fileName.Replace(" ", "");
      hpf.SaveAs(fileName);
      createThumbnail(fileName);
    }
  }
}

private void createThumbnail(string filename)
{
  Image image = Image.FromFile(filename);
  Image thumb = image.GetThumbnailImage(100,100, () => false, IntPtr.Zero);
  thumb.Save(filename);
  image.Dispose();
  thumb.Dispose();
 }

Please let me know if this works any better: 请让我知道这是否更好:

    public string ImageDirectory { get { return Server.MapPath(@"~\images\"); } }

    public void OnUploadClick(object sender, EventArgs e)
    {
        var files = HttpContext.Request.Files.AllKeys.AsEnumerable()
            .Select(k =>HttpContext.Request.Files[k]);

        foreach(var file in files)
        {
            if(file.ContentLength <= 0)
                continue;

            string savePath = GetFullSavePath(file);
            var dimensions = new Size(100, 100);

            CreateThumbnail(file,savePath,dimensions);
        }
    }

    private void CreateThumbnail(HttpPostedFile file,string savePath, Size dimensions)
    {
        using (var image = Image.FromStream(file.InputStream))
        {
            using (var thumb = image.GetThumbnailImage(dimensions.Width, dimensions.Height, () => false, IntPtr.Zero))
            {
                thumb.Save(savePath);
            }
        }
    }

    private string GetFullSavePath(HttpPostedFile file)
    {
        string fileName = System.IO.Path.GetFileName(file.FileName).Replace(" ", "");
        string savePath = System.IO.Path.Combine(this.ImageDirectory, fileName);
        return savePath;
    }

Edit - 编辑-

The foreach should have followed more to this pattern: foreach应该更多地遵循此模式:

var files = HttpContext.Request.Files.AllKeys.AsEnumerable()
                .Select(k =>HttpContext.Request.Files[k]);

foreach(var file in files)
{

}

You can try this code to create your thumbnails. 您可以尝试使用此代码创建缩略图。

       MemoryStream ms = new MemoryStream(File.ReadAllBytes(path));
       Bitmap originalBMP = new Bitmap(ms);

       int maxWidth = 200;
       int maxHeight = 200;

       // Calculate the new image dimensions 
       int origWidth = originalBMP.Width;
       int origHeight = originalBMP.Height;
       double sngRatio = Convert.ToDouble(origWidth) / Convert.ToDouble(origHeight);

       // New dimensions
       int newWidth = 0;
       int newHeight = 0;
       try
       {
           // max 200 by 200

           if ((origWidth <= maxWidth && origHeight <= maxHeight) || origWidth <= maxWidth)
           {
               newWidth = origWidth;
               newHeight = origHeight;
           }
           else
           {
               // Width longer (shrink width)
               newWidth = 200;
               newHeight = Convert.ToInt32(Convert.ToDouble(newWidth) / sngRatio);
           }

           // Create a new bitmap which will hold the previous resized bitmap 
           Bitmap newBMP = new Bitmap(originalBMP, newWidth, newHeight);
           // Create a graphic based on the new bitmap 
           Graphics oGraphics = Graphics.FromImage(newBMP);

           // Set the properties for the new graphic file 
           oGraphics.SmoothingMode = SmoothingMode.AntiAlias;
           oGraphics.InterpolationMode = InterpolationMode.High;
           // Draw the new graphic based on the resized bitmap 
           oGraphics.CompositingQuality = CompositingQuality.HighSpeed;

           oGraphics.DrawImage(originalBMP, 0, 0, newWidth, newHeight);

           // Save the new graphic file to the server 
           EncoderParameters p = new EncoderParameters(1);
           p.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, 70);     // Percent Compression

           MemoryStream savedBmp = new MemoryStream();

           newBMP.Save(savedBmp, ImageCodecInfo.GetImageEncoders()[1], p);

                          // Once finished with the bitmap objects, we deallocate them. 
           originalBMP.Dispose();
           newBMP.Dispose();
           oGraphics.Dispose();
           savedBmp.Dispose();

Certainly a bit more work but it does give you greater control. 当然,还有更多工作要做,但确实可以给您更大的控制权。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM