我正在创建一个像这样的目录:
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)
尝试使用Sysinternals Procmon工具查看“幕后发生的事情”。
答案 1 :(得分:0)
Microsoft documentation提供了保存位图时ExternalException的一些原因。 (你把这些排除了吗?)