how to close a file and delete that image file? - c#

Imagename = objUser.UserID + filename;
Imagepath = "D:\\Shop\\ShopMonkey\\Images" + Imagename;
FileUpload.SaveAs(Path.Combine(#"D:\ShopMonkey_Web_21-6-12\ShopMonkey\Images", Imagename));
objUser.UploadImagePath = Imagepath;
objUser.UploadImagename = Imagename;
System.Drawing.Image img1 = System.Drawing.Image.FromFile(Imagepath);
System.Drawing.Image bmp1 = img1.GetThumbnailImage(50, 50, null, IntPtr.Zero);
ThumbNailPath = "D:\\ShopMonkey_Web_21-6-12\\ShopMonkey\\ThumbNails" + Imagename;
bmp1.Save(Path.Combine(#"D:\ShopMonkey_Web_21-6-12\ShopMonkey\ThumbNails", Imagename));
objUser.UploadThumbnailPath = ThumbNailPath;
How to delete the image and thumbnail in other function? (Is it necessary to close that first or not?)

I'm guessing that you're trying to delete a file on disk if it already exists for this user upon asp.net upload of an image by that same user again.
This method will delete both image and thumbnail if they exist.
Keep your image creation activities separate from your image clean up activities to keep your intent clear and your code maintainable.
// replace with an entry loaded from a config file
const string ImageRoot = #"D:\ShopMonkey_Web_21-6-12\ShopMonkey";
// replace this is your user instance
object user = new object();
string Imagename = objUser.UserID + filename;
string uploadImagePath = Path.Combine(ImageRoot, "Images", Imagename);
string thumbnailPath = Path.Combine(ImageRoot, "ThumbNails", Imagename);
objUser.UploadImagePath = uploadImagePath;
objUser.UploadImagename = Imagename;
objUser.UploadThumbnailPath = thumbnailPath;
// delete both if they exist
if (File.Exists(uploadImagePath))
File.Delete(uploadImagePath);
if (File.Exists(thumbnailPath))
File.Delete(thumbnailPath);
// replace this with your uploaded file details
object fileInfo = new object();
using (System.Drawing.Image img1 = System.Drawing.Image.FromFile(uploadImagePath)) {
img1.Save(uploadImagePath);
using (System.Drawing.Image bmp1 = img1.GetThumbnailImage(50, 50, null, IntPtr.Zero)) {
bmp1.Save(thumbnailPath);
}
FileUpload.SaveAs(uploadImagePath);
}

Related

Deleting file throws file in use exception

I have a file upload control that allows users to upload an image file. Rather then forcing them to use a specific size image, I am trying to resize it, save it the resized version to a folder and then delete the original.
When I try to delete the file, I keep getting "file in use" exception. I have searched and tried all suggestions to no avail.
This is the latest try, at which point I decided to seek help. I pass the source path (where original file is in, a destination path where resized file is to end up in, file name and width to which it should be resized, keeping aspect ratio):
public static void CreateResizedCopy(String sourcePath, String destinationPath, String filename, int width)
{
if (!File.Exists(destinationPath + filename))
{
System.Drawing.Image image = System.Drawing.Image.FromFile(sourcePath + filename);
float AspectRatio = (float)image.Size.Width / (float)image.Size.Height;
int newHeight = Convert.ToInt32(width / AspectRatio);
Bitmap thumbnailBitmap = new Bitmap(width, newHeight);
Graphics thumbnailGraph = Graphics.FromImage(thumbnailBitmap);
thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality;
thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality;
thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
var imageRectangle = new Rectangle(0, 0, width, newHeight);
thumbnailGraph.DrawImage(image, imageRectangle);
thumbnailBitmap.Save(destinationPath + filename, ImageFormat.Jpeg);
thumbnailGraph.Dispose();
thumbnailBitmap.Dispose();
image.Dispose();
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
if (!FileInUse(sourcePath + filename))
{
File.Delete(sourcePath + filename);
}
else
{
// Error here: file is in use
using (FileStream fs = new FileStream(sourcePath + filename, FileMode.OpenOrCreate))
fs.Dispose();
}
}
}
public static bool FileInUse(string path)
{
try
{
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
{
return false;
}
}
catch (IOException ex)
{
return true;
}
}
UPDATE
This is the AJAX AsynFileUpload's upload completed event handler. It saves the file to a "Resize" folder. If image needs to be resized, it calls the method to resize it and then moves it to its final resting place. If not, no resizing is done, it just moves the file. It then "attempts" to delete the file in resize folder and it chokes!
protected void fuNewsImage_UploadedComplete_Resize(object sender, AsyncFileUploadEventArgs e)
{
if (fuNewsImage.HasFile)
{
HttpPostedFile file = fuNewsImage.PostedFile;
string sFileName = fuNewsImage.FileName;
string sFileSize = e.FileSize;
string sSaveFolder = ImageFilePath.TEMP_FOLDER_EA_TEST + "\\";
string sResizeFolder = ImageFilePath.TEMP_FOLDER_EA_TEST + "\\Resized\\";
fuNewsImage.SaveAs(Server.MapPath(sResizeFolder + sFileName));
System.Drawing.Image img = System.Drawing.Image.FromFile(Server.MapPath(sResizeFolder) + sFileName);
int iImgWidth = img.Width;
int iImgHeight = img.Height;
if (iImgWidth > ImageInfo.MAX_WIDTH)
{
// sSaveFolder is the efinal resting place of the uploaded image
// If image width is more than max allowed, resize it, save it in sSaveFolder
Utils.CreateResizedCopy(Server.MapPath(sResizeFolder), Server.MapPath(sSaveFolder), sFileName, 600);
System.Threading.Thread.Sleep(1000);
File.Delete(Server.MapPath(sSaveFolder + sFileName));
}
else // just move it t sSaveFolder
{
File.Move(Server.MapPath(sResizeFolder) + sFileName, Server.MapPath(sSaveFolder) + sFileName);
}
// --- Chokes here ---
Array.ForEach(Directory.GetFiles(Server.MapPath(sResizeFolder)), File.Delete);
}
}

The process cannot access the file because it is being used by another process error while moving image

I've a folder named testPhotos with some images. Based on the image creation date, I want to create a new folder by image creation year and then move the image to that folder.
For example, testPhotos has image named 01.jpg which was created on 2011. So I want to create a folder named 2011 inside testPhotos like testPhotos\2011 and move image to that folder. While doing this I am getting The process cannot access the file because it is being used by another process. error while moving image from one folder to another.
Code:
private void button1_Click(object sender, EventArgs e)
{
var creationDate = new DateTime();
var dateList = new List<String>();
var fileName = String.Empty;
var sourceFolder = #"C:\My Stuff\Test Porjects\testPhotos";
String[] images = Directory.GetFiles(sourceFolder);
if (images.Count() > 0)
{
foreach (var imagePath in images)
{
fileName = Path.GetFileName(imagePath);
creationDate = GetDateTakenFromImage(imagePath);
var date = creationDate.GetDateTimeFormats()[5].Replace("-", "/");
if (!String.IsNullOrEmpty(date))
{
var year = date.Substring(0, 4);
var destinationFolder = sourceFolder + "\\" + year;
if (!Directory.Exists(destinationFolder))
{
Directory.CreateDirectory(destinationFolder);
String fileToMove = sourceFolder+ "\\" + fileName;
String moveTo = destinationFolder + "\\" + fileName;
File.Move(fileToMove, moveTo);
}
}
}
}
}
private DateTime GetDateTakenFromImage(string path)
{
Image myImage = Image.FromFile(path);
PropertyItem propItem = myImage.GetPropertyItem(36867);
string dateTaken = new Regex(":").Replace(Encoding.UTF8.GetString(propItem.Value), "-", 2);
return DateTime.Parse(dateTaken);
}
Any ideas?
This looks like a missing dispose on the image, try with the following:
private DateTime GetDateTakenFromImage(string path)
{
using (Image myImage = Image.FromFile(path))
{
PropertyItem propItem = myImage.GetPropertyItem(36867);
string dateTaken = new Regex(":").Replace(Encoding.UTF8.GetString(propItem.Value), "-", 2);
return DateTime.Parse(dateTaken);
}
}

Release a file being used by another process

I'm implementing "copy map to clip" as an image.
what I do is I create an image an save it to certain directory and copy it to clipboard.
but before I do that I delete every file that exist in the directory, but now I cant since, the image is being used by clipboard.
here's my code.
public override void OnClick()
{
//base.OnClick();
DeleteOldCopiedJPG();
System.Windows.Forms.Clipboard.Clear();
string fileName = System.Windows.Forms.Application.ExecutablePath.Substring(0, System.Windows.Forms.Application.ExecutablePath.LastIndexOf("\\") + 1) + Guid.NewGuid() + ".jpg";
//System.Windows.Forms.Cursor.Current = Cursors.Wait;
//if (System.IO.File.Exists(fileName))
// System.IO.File.Delete(fileName);
IExport objExport = (IExport)new ExportJPEG();
objExport.ExportFileName = fileName;
#if Debug || Release
ESRI.ArcGIS.Display.tagRECT objExportRECT = default( ESRI.ArcGIS.Display.tagRECT);
#else
tagRECT objExportRECT = default(tagRECT);
#endif
var _with1 = objExportRECT;
_with1.left = mapControl.ActiveView.ExportFrame.left;
_with1.top = mapControl.ActiveView.ExportFrame.top;
_with1.right = mapControl.ActiveView.ExportFrame.right;
_with1.bottom = mapControl.ActiveView.ExportFrame.bottom;
IEnvelope envelope = new EnvelopeClass();
envelope.PutCoords(mapControl.ActiveView.ExportFrame.left, mapControl.ActiveView.ExportFrame.top,
mapControl.ActiveView.ExportFrame.right, mapControl.ActiveView.ExportFrame.bottom);
objExport.PixelBounds = envelope;
System.Int32 intHDC = objExport.StartExporting();
mapControl.ActiveView.Output(intHDC, Convert.ToInt16(objExport.Resolution), objExportRECT, null, null);
objExport.FinishExporting();
objExport.Cleanup();
System.Drawing.Image objImage = System.Drawing.Bitmap.FromFile(fileName);
System.Windows.Forms.Clipboard.SetImage(objImage);
//RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32);
//renderTargetBitmap.Render((Visual)mapControl.ActiveView.ScreenDisplay);
//Clipboard.SetImage(renderTargetBitmap);
}
private void DeleteOldCopiedJPG(string Path)
{
string[] filePaths = Directory.GetFiles(System.Windows.Forms.Application.ExecutablePath.Substring(0, System.Windows.Forms.Application.ExecutablePath.LastIndexOf("\\") + 1));
foreach (string filepath in filePaths)
if (filepath.Substring(filepath.Length - 4) == ".jpg")
try{ File.Delete(filepath); } catch {}
}
You need to dispose the image after inserting it into the clipboard:
using (System.Drawing.Image objImage = System.Drawing.Bitmap.FromFile(fileName))
{
System.Windows.Forms.Clipboard.SetImage(objImage);
}
Otherwise it will remain open until the garbage collector calls the finalizer for objImage.

C# file access error

I have the following C# code :
string selectedFile = "D:\..\IMGP2695.JPG";
MyImage myImage = new MyImage();
Image image = Image.FromFile(selectedFile);
string thumbnail_name = CreateThumbnail(image);
myImage.height = image.Height + "px";
myImage.width = image.Width + "px";
ftp.upload(myImage.internalName, selectedFile, directory);
The process cannot access the file `'D:\..\IMGP2695.JPG'` because it is being used by another process.
I get this error when the code try to run ftp.upload. I know what the error means but i don't know what to do to close the handle to the opened file.
Try to dispose image object by wrapping Image.FromFile with using:
string selectedFile = "D:\..\IMGP2695.JPG";
MyImage myImage = new MyImage();
string thumbnail_name = string.empty;
using(Image image = Image.FromFile(selectedFile)){
thumbnail_name = CreateThumbnail(image);
myImage.height = image.Height + "px";
myImage.width = image.Width + "px";
}
ftp.upload(myImage.internalName, selectedFile, directory);
Because you calling Image image = Image.FromFile(selectedFile); before uploading , for some reason.
If you look on Image.FromFile documentation you will see the following string:
The file remains locked until the Image is disposed.
That means, that according to the code provided, you can init Image even after the upload finished.
ftp.upload("NAME_OF_THE_FILE_RECOVERED_FROM_FILE_ITSELF", selectedFile, directory);
Image image = Image.FromFile(selectedFile);

Web API handle uploaded files for delete

ok I have this code that handle a file been upload through a simple web form
CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(#"C:\inetpub\wwwroot\myapp\Images");
//var provider = new MultipartFormDataStreamProvider(#"C:\inetpub\wwwroot\myapp\Images");
var Image = "";
var Dir = "";
var CurrentPath = "";
string UploadType = "";
string ImageName = "";
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// Show all the key-value pairs.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
if (key == "uploadType") UploadType = val;
if (key == "imageName") ImageName = val;
//Trace.WriteLine(string.Format("{0}: {1}", key, val));
}
}
foreach (MultipartFileData file in provider.FileData)
{
//Debug.WriteLine(file.Headers.ContentDisposition.FileName);
//Debug.WriteLine("Server file path: " + file.LocalFileName);
Image = Path.GetFileName(file.LocalFileName);
Dir = Path.GetDirectoryName(file.LocalFileName);
CurrentPath = file.LocalFileName;
}
if (UploadType == "update")
{
File.Delete(Dir + "\\" + Image);
File.Move(CurrentPath, Dir + "\\" + Image);
Imagen = ImageName;
}
return Request.CreateResponse(HttpStatusCode.OK, Image);
as some docs mention using await will cause the read process to be async, my problem is that I need to know when the file has been saved into the folder cause I want to delete it after if the UploadType form field is == to update, but it seems like when try this line
File.Delete(Dir + "\\" + Image);
the image is has not been saved yet and I got an error that the image don't exist, so my question is, how I can tell or be sure the image is ready in the dir? how can I tell the async process ends, thanks for any help on this!!
File.Exists is the method you should use.
Aside You should be using Path.Combine instead of building the path with concatenation.

Categories