2011-12-24 3 views
2

Я создаю каталог как так:Bitmap не может сохранять файлы в каталог, который был только что создан программно

Directory.CreateDirectory(context.Server.MapPath(String.Format("Uploads/{0}/Main", currentUploadDir + 1))); 

После того, как выше создается каталог, я пытаюсь использовать метод Bitmap.Save для сохранения изображения в этот каталог, как так:

bitmap.Save(outFile, jpgEncoder, ep); 

выше метод сохранения не удается, и я представил со следующим исключением:

An exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll but was not handled in user code 

Additional information: A generic error occurred in GDI+. 

Если я создаю один и тот же каталог (в том же пути) вручную через проводник Windows, метод Bitmap.Save может создать изображение без каких-либо проблем.

Сначала, хотя это может быть проблема с разрешениями. Но в обоих случаях (создание каталога программно или вручную) правильные разрешения наследуются из родительского каталога. Итак, я вижу, что это проблема.

Кто-нибудь знает, в чем причина этого исключения?

Это код обработчика HTTP, который страдает от проблемы я описываю выше:

public class FileUpload : IHttpHandler, IRequiresSessionState 
{ 
    private static ImageCodecInfo jpgEncoder; 

    public void ProcessRequest(HttpContext context) 
    { 
     if (context.Request.Files.Count > 0) 
     { 
      int providerId = 0; 
      int employeeId = 0; 

      int chunk = context.Request["chunk"] != null ? int.Parse(context.Request["chunk"]) : 0; 
      int chunks = context.Request["chunks"] != null ? int.Parse(context.Request["chunks"]) : 0; 

      int currentUploadDir = 0; 

      if (chunk == 0) 
      { 
       currentUploadDir = GetCurrentActiveUploadDirectory(context); 
       context.Session["CurrentUploadDir"] = currentUploadDir; 
      } 
      else 
      { 
       currentUploadDir = Convert.ToInt32(context.Session["CurrentUploadDir"]); 
      } 

      string mainImgPath = String.Format("Uploads/{0}/Main", currentUploadDir); 
      string thumbImgPath = String.Format("Uploads/{0}/Thumb", currentUploadDir); 
      string mobileImgPath = String.Format("Uploads/{0}/Mobile", currentUploadDir); 

      // Get the provider id. 
      if (!String.IsNullOrEmpty(context.Request.QueryString["ProviderId"])) 
      { 
       providerId = Convert.ToInt32(context.Request.QueryString["ProviderId"]); 
      } 
      else 
      { 
       return; 
      } 

      // Get the employee id. 
      if (!String.IsNullOrEmpty(context.Request.QueryString["EmployeeId"])) 
      { 
       employeeId = Convert.ToInt32(context.Request.QueryString["EmployeeId"]); 
      } 
      else 
      { 
       return; 
      } 

      // If we already have 7 images for this provider, we will silently fail to add any more images. 
      if (Company.GetFileCount(providerId) < 7) 
      { 
       string fileName = String.Empty; 

       if (chunk == 0) 
       { 
        Company company = Company.GetCompany(providerId); 

        File file = File.NewFile(); 
        file.FileCategory = "Facility Photo"; 
        file.Featured = 0; 
        file.Cover = 0; 
        file.Status = "A"; 
        file.FileUrl = mainImgPath; 
        file.ProviderId = providerId; 
        file.EmployeeId = employeeId; 
        file = file.Save(); 

        fileName = context.Request["name"] != null ? context.Request["name"] : string.Empty;      

        // Create SEO friendly name to images [space-city-state-number] 
        // Space = Provider Id. 
        // City = City (DB field). 
        // State = State (DB field). 
        // Number = Incremental value for each image (i.e. 1, 2, 3, ...). 
        fileName = String.Concat(company.BranchDept.Replace(' ', '_'), "-", 
               String.IsNullOrEmpty(company.City) ? String.Empty : String.Concat(company.City.Replace(' ', '_'), "-"), 
               String.IsNullOrEmpty(company.State) ? String.Empty : String.Concat(company.State.Replace(' ', '_'), "-"), 
               file.Id, 
               fileName.Substring(fileName.LastIndexOf('.'), fileName.Length - fileName.LastIndexOf('.'))); 

        file.FileName = fileName; 
        file.FileDescription = fileName; 
        file.FileType = context.Request.Files[0].ContentType; 
        file.Save(); 

        context.Session["UploadFileName"] = fileName; 
       } 
       else 
       { 
        fileName = context.Session["UploadFileName"].ToString(); 
       } 

       HttpPostedFile fileUpload = context.Request.Files[0]; 

       // Create and save the main image. 
       using (var fs = new FileStream(Path.Combine(context.Server.MapPath(mainImgPath), fileName), chunk == 0 ? FileMode.Create : FileMode.Append)) 
       { 
        var buffer = new byte[fileUpload.InputStream.Length]; 
        fileUpload.InputStream.Read(buffer, 0, buffer.Length); 
        fs.Write(buffer, 0, buffer.Length); 
       } 

       // We will only create the thumbnail and mobile images if this is the last chunk of the main image. 
       if ((chunk + 1) == chunks) 
       { 
        // Create, resize and save the thumbnail image. 
        ResizeImage(Path.Combine(context.Server.MapPath(mainImgPath), fileName), 45, Path.Combine(context.Server.MapPath(thumbImgPath), fileName)); 

        // Create, resize and save the mobile image. 
        ResizeImage(Path.Combine(context.Server.MapPath(mainImgPath), fileName), 10, Path.Combine(context.Server.MapPath(mobileImgPath), fileName)); 
       } 
      } 
     } 
    } 

    /// <summary> 
    /// Determines what the current upload directory is and if a new one needs to be created. 
    /// </summary> 
    /// <param name="context">Http context object.</param> 
    /// <returns>Integer value representing the current upload directoy.</returns> 
    private static int GetCurrentActiveUploadDirectory(HttpContext context) 
    { 
     // Get the current active directory for file upload. 
     DirectoryInfo uploadsDir = new DirectoryInfo(context.Server.MapPath("Uploads")); 
     DirectoryInfo[] subDirectories = uploadsDir.GetDirectories(); 

     List<int> subDirNames = new List<int>(); 

     foreach (DirectoryInfo dir in subDirectories) 
     { 
      if (Utilities.IsNumeric(dir.Name, System.Globalization.NumberStyles.Integer)) 
      { 
       subDirNames.Add(Convert.ToInt32(dir.Name)); 
      } 
     } 

     subDirNames.Sort(); 

     int currentUploadDir = subDirNames[subDirNames.Count - 1]; 

     // Get the count of files in the current active upload directory. 
     int fileCount = Directory.GetFiles(context.Server.MapPath(String.Format("Uploads/{0}", currentUploadDir)), "*.*", SearchOption.AllDirectories).Length; 

     // Determine if a new active upload directory needs to be created. 
     if (fileCount > 25) // 7000 in each one of the 3 subdirectories (Main, Thumb, Mobile). 
     { 
      // Create a new active directory structure. 
      //uploadsDir.CreateSubdirectory(String.Format("{0}/Main", currentUploadDir + 1)); 
      //uploadsDir.CreateSubdirectory(String.Format("{0}/Thumbnail", currentUploadDir + 1)); 
      //uploadsDir.CreateSubdirectory(String.Format("{0}/Mobile", currentUploadDir + 1)); 

      Directory.CreateDirectory(context.Server.MapPath(String.Format("Uploads/{0}/Main", currentUploadDir + 1))); 
      Directory.CreateDirectory(context.Server.MapPath(String.Format("Uploads/{0}/Thumbnail", currentUploadDir + 1))); 
      Directory.CreateDirectory(context.Server.MapPath(String.Format("Uploads/{0}/Mobile", currentUploadDir + 1))); 

      currentUploadDir++; 
     } 

     return currentUploadDir; 
    } 

    /// <summary> 
    /// Resizes and saves the specified image. 
    /// </summary> 
    /// <param name="inFile">The file path of the image to be resized.</param> 
    /// <param name="maxDimension">The max height or width that the image will be resized to.</param> 
    /// <param name="outFile">The file path of the resized image.</param> 
    private void ResizeImage(string inFile, int maxDimension, string outFile) 
    { 
     using (Stream stream = new FileStream(inFile, FileMode.Open)) 
     { 
      using (Image inImage = Image.FromStream(stream)) 
      { 
       double width; 
       double height; 
       if (inImage.Height < inImage.Width) 
       { 
        width = maxDimension; 
        height = (maxDimension/(double)inImage.Width) * inImage.Height; 
       } 
       else 
       { 
        height = maxDimension; 
        width = (maxDimension/(double)inImage.Height) * inImage.Width; 
       } 
       using (Bitmap bitmap = new Bitmap((int)width, (int)height)) 
       { 
        using (Graphics graphics = Graphics.FromImage(bitmap)) 
        { 
         graphics.SmoothingMode = SmoothingMode.HighQuality; 
         graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 
         graphics.DrawImage(inImage, 0, 0, bitmap.Width, bitmap.Height); 

         if (inImage.RawFormat.Guid == ImageFormat.Jpeg.Guid) 
         { 
          if (jpgEncoder == null) 
          { 
           ImageCodecInfo[] ici = ImageCodecInfo.GetImageDecoders(); 

           foreach (ImageCodecInfo info in ici) 
           { 
            if (info.FormatID == ImageFormat.Jpeg.Guid) 
            { 
             jpgEncoder = info; 
             break; 
            } 
           } 
          } 

          if (jpgEncoder != null) 
          { 
           EncoderParameters ep = new EncoderParameters(1); 
           //A quality level of 0 corresponds to the greatest compression, and a quality level of 100 corresponds to the least compression. 
           ep.Param[0] = new EncoderParameter(Encoder.Quality, 100L); 
           bitmap.Save(outFile, jpgEncoder, ep); 
          } 
          else 
          { 
           bitmap.Save(outFile, inImage.RawFormat); 
          } 
         } 
         else 
         { 
          // Fill with white for transparent GIFs 
          graphics.FillRectangle(Brushes.White, 0, 0, bitmap.Width, bitmap.Height); 
          bitmap.Save(outFile, inImage.RawFormat); 
         } 
        } 
       } 
      } 
     } 
    } 

    public bool IsReusable 
    { 
     get 
     { 
      return false; 
     } 
    } 
} 
+0

Чтобы созданный вами каталог был таким же, как тот, который вы пытаетесь записать, создайте строку каталога и сохраните ее в переменной. Затем используйте обе функции. –

+0

Можете ли вы показать связь между 'outFile' и созданной папкой? –

+0

Я просто добавил исходный код, на который ссылается мой вопрос. – bbeny

ответ

0

Попробуйте использовать Sysinternals Procmon инструмент, чтобы увидеть, что происходит «под одеялом».

0

Microsoft documentation предоставляет некоторые причины для внешнего исключения при сохранении растрового изображения. (Вы их исключили?)

+0

Я проверил эти причины. Но, из описания Microsoft, я не верю, что любая из них является причиной моей проблемы. Microsoft заявляет, что причиной может быть то, что изображение было сохранено с неправильным форматом изображения (что, я уверен, не так). Или изображение было сохранено в том же файле, из которого он был создан (что, я думаю, тоже не так). – bbeny

+0

Затем попробуйте использовать Procmon, чтобы узнать, что происходит. – jdigital

+0

Я пробовал использовать Procmon, но ничего интересного не появлялось. Было много активности ввода-вывода с папкой, в которой я пишу изображение, но ничего, что связано с тем исключением, которое я получаю. – bbeny

Смежные вопросы