位图无法将文件保存到刚刚以编程方式创建的目录中

时间:2011-12-24 18:12:17

标签: c# asp.net 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;
        }
    }
}

2 个答案:

答案 0 :(得分:0)

尝试使用Sysinternals Procmon工具查看“幕后发生的事情”。

答案 1 :(得分:0)

Microsoft documentation提供了保存位图时ExternalException的一些原因。 (你把这些排除了吗?)