Deleting files gives an error (The process cannot access the file..) - c#

I'm currently debugging my code because it gives me an error:
The process cannot access the file because it is being used by another process.
And i think that the error occurs in this lines of code
foreach (var filename in filenames)
{
var file = Path.Combine(filePath, filename);
mail.Attachments.Add(new Attachment(file));
}
// Send Mail
smtpServer.Send(mail);
DeleteFiles();
I want to delete the files in the folder when the mail is sent using this method
private void DeleteFiles()
{
string filePath = Server.MapPath("~/Content/attachments");
Array.ForEach(Directory.GetFiles(filePath), System.IO.File.Delete);
}
I read about closing/disposing? FileStream and etc. but how can i use that in my code? Thanks in advance.

mail.dispose(); You should dispose mail before deleting the file. This should remove the lock on the file.
foreach (var filename in filenames)
{
var file = Path.Combine(filePath, filename);
mail.Attachments.Add(new Attachment(file));
}
// Send Mail
smtpServer.Send(mail);
mail.Dispose();
DeleteFiles();
https://msdn.microsoft.com/en-us/library/0w54a951(v=vs.110).aspx

using(FileStream stream = new FileStream("thepath"))
{
//do stuff with the file
stream .Close();
}
Now the stream will be closed and disposed.

Related

How can I delete the old one while uploading a new image with c #

I want to delete old image when uploading new one with c# but I get
the process cannot access the file because it is being used by another process. error
public void DeleteExistImage(string imageName)
{
string path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images/" + imageName);
using (var stream = new FileStream(path, FileMode.Create))
{
stream.Dispose();
System.IO.File.Delete(path);
}
}
Try this to delete the file and then create a new file
string path = #"c:\mytext.txt";
if (File.Exists(path))
{
File.Delete(path);
}
Also, look into the thread if it solves your issue
IOException: The process cannot access the file 'file path' because it is being used by another process

Stream was not readable with Using

I am getting an error
File is being used by another process
trying to implement using for a FileStream. However, I encountered the error of Stream was not readable.
This is my code:
Before: working, but encounters 'file being used by another process' error periodically
EmailMessage responseMessageWithAttachment = responseMessage.Save();
foreach (var attachment in email.Attachments)
{
if (attachment is FileAttachment)
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load();
fileAttachment.Load(AppConfig.EmailSaveFilePath + fileAttachment.Name);
FileStream fs = new FileStream(AppConfig.EmailSaveFilePath + fileAttachment.Name, FileMode.OpenOrCreate);
responseMessageWithAttachment.Attachments.AddFileAttachment(attachment.Name, fs);
}
}
responseMessageWithAttachment.SendAndSaveCopy();
After: encounters 'stream was not readable' error
EmailMessage responseMessageWithAttachment = responseMessage.Save();
foreach (var attachment in email.Attachments)
{
if (attachment is FileAttachment)
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load();
fileAttachment.Load(AppConfig.EmailSaveFilePath + fileAttachment.Name);
using (FileStream fs = new FileStream(AppConfig.EmailSaveFilePath + fileAttachment.Name, FileMode.OpenOrCreate))
{
responseMessageWithAttachment.Attachments.AddFileAttachment(attachment.Name, fs);
};
}
}
responseMessageWithAttachment.SendAndSaveCopy();
working, but encounter 'file being used by another process' error periodically
This means what it says: some other process is touching the file. If you want to solve this, you need to figure out what's using the file. This will happen whether you use using or not.
If this code is running multiple times in parallel, it could be your own code interfering. Either way, you could avoid it by open for reading only, but specifically allowing other processes to open it for writing. You would do that like this:
var fs = new FileStream(Path.Combine(AppConfig.EmailSaveFilePath, fileAttachment.Name),
FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
encounter 'stream was not readable' error
This depends on how AddFileAttachment is implemented. You don't show the stack trace, so it's possible that it doesn't read the stream until you call SendAndSaveCopy(), which is outside the using and the stream is closed.
An easy way to work around this is to just use the overload of AddFileAttachment that just takes the path to the file as a string, so you don't need to manage the FileStream yourself:
responseMessageWithAttachment.Attachments.AddFileAttachment(attachment.Name,
Path.Combine(AppConfig.EmailSaveFilePath, fileAttachment.Name));
I use Path.Combine since it avoids problems where there may or may not be a trailing \ in your EmailSaveFilePath setting.
I wonder if you can avoid saving the files and just use Content and AddFileAttachment(String, Byte[])
foreach (var attachment in email.Attachments)
{
if (attachment is FileAttachment)
{
FileAttachment fileAttachment = attachment as FileAttachment;
fileAttachment.Load();
responseMessageWithAttachment.Attachments.AddFileAttachment(attachment.Name, fileAttachment.Content);
}
}
responseMessageWithAttachment.SendAndSaveCopy();

Is there a way to Extract attachment from Email Message Mime Content without using Exchange Service?

I am having a client application which will save eml files to the local disk. Need to get the attachment inside the eml file which is saved without using the exchange service because the Mailbox keeps changing of its capacity.Please help if anyone have come across similar issue
I have tried the reverse process of getting the eml file and load it again to get the details.
You could use something like MimeKit for this. The GitHub page has examples on how to parse MIME messages and how to get attachments.
Here is an example of how to get the attachments in an array of bytes:
var mimeMessage = MimeMessage.Load(#"test.eml");
var attachments = mimeMessage.Attachments.ToList();
foreach (var attachment in attachments)
{
using (var memory = new MemoryStream())
{
if (attachment is MimePart)
((MimePart)attachment).Content.DecodeTo(memory);
else
((MessagePart)attachment).Message.WriteTo(memory);
var bytes = memory.ToArray();
}
}
First of all Big Thanks to MadDev for helping out !!!
Here is the Code which I used:
Note: Here in case, the stored email will always have another eml file attached to it and this is based on the business logic.
protected static void MimeProcessor(MemoryStream stream)
{
try
{
var parser = new MimeParser(stream, MimeFormat.Default);
var message = parser.ParseMessage();
var multipart = message.Body as Multipart;
//Found the Attachment as Message Part
var OriginalMessage = multipart.ToList().LastOrDefault();
if (OriginalMessage is MessagePart)
{
using (var memory = new MemoryStream())
{
((MessagePart)OriginalMessage).Message.WriteTo(memory);
var bytes = memory.ToArray();
File.WriteAllBytes("C:\\Test\\TestMessage.eml", bytes);
}
}
}
catch (Exception)
{
throw;
}
}

Cannot access a closed file in ASP.Net (saving files in zip file)

I got this error "Cannot access a closed file" when I save more than one file in zip.
This is the code. Error at zip.Save(NewZipPath);
internal static string UpdateZipFile(string PdfPath, string ZipPath,
string NewZipPath, string docPath)
{
try
{
using (ZipFile zip = ZipFile.Read(ZipPath))
{
FileStream fs = new FileStream(PdfPath, FileMode.Open, FileAccess.Read);
DirectoryInfo Dir = new DirectoryInfo(docPath);
FileInfo[] FileList = Dir.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo FI in FileList)
{
zip.AddEntry(FI.FullName, fs);
}
// Error at this line if more than one
// files in above directory.
zip.Save(NewZipPath);
fs.Close();
fs.Dispose();
return "- ZIP Generated Successfully !";
}
}
catch (Exception ex)
{
return ex.Message;
}
}
Full exception
System.ObjectDisposedException: Cannot access a closed file.
at System.IO.__Error.FileNotOpen()
at System.IO.FileStream.get_Length()
at Ionic.Zip.ZipEntry.SetInputAndFigureFileLength(Stream& input)
at Ionic.Zip.ZipEntry._WriteEntryData(Stream s)
at Ionic.Zip.ZipEntry._EmitOne(Stream outstream)
at Ionic.Zip.ZipEntry.Write(Stream s)
at Ionic.Zip.ZipFile.Save()
at Ionic.Zip.ZipFile.Save(String fileName)
at RideShare.Utility.UpdateZipFile(String PdfPath,
String ZipPath, String NewZipPath, String docPath) in
Thanks.
I think what's going on here is that the use of the stream "FS" is tangled up. You can spend time trying to untangle it, or you can use the simpler "AddFiles" method:
Search for "Create a zip containing all the files in a folder." at
http://dotnetzip.codeplex.com/wikipage?title=CS-Examples&referringTitle=Examples
the exception happens because AddEntry uses the FileStram and after it is finished with the FileStream it closes it automatically.. so it is closed during Save after the first file... when there is one file it is ok - but your code adds the same FileStream fs for every file... not sure that this is what you really want... I think you would want to open one separate stream per file you add via AddEntry...
change your code to:
foreach (FileInfo FI in FileList)
{
zip.AddFile(FI.FullName);
}
OR replace the foreach loop by
zip.AddFiles((from FI in Dir.GetFiles("*.*", SearchOption.AllDirectories) select FI.FullName).ToArray());

HttpContext.Current.Response write file after download manager starts

I'm trying to create a ZIP file on the fly which might contain a few thousands of pictures.
public static void CompressAndSendFiles(List files)
{
HttpContext.Current.Response.ClearContent();
// LINE1: Add the file name and attachment, which will force the open/cance/save dialog to show, to the header
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"Jpeg Package "
+ DateTime.Now.ToString("MM-dd-yyyy hh-mm-ss") + ".zip\"");
// Add the file size into the response header
//HttpContext.Current.Response.AddHeader("Content-Length", file.Length.ToString());
// Set the ContentType
HttpContext.Current.Response.ContentType = ReturnHttpContentType("download.zip");
ZipOutputStream oZipStream =
new ZipOutputStream(HttpContext.Current.Response.OutputStream);
try
{
foreach (string file in files)
{
FileInfo fInfo = new FileInfo(file);
ZipEntry oZipEntry = new ZipEntry(fInfo.Name);
oZipStream.PutNextEntry(oZipEntry);
byte[] buffer = File.ReadAllBytes(file);
oZipStream.Write(buffer, 0, buffer.Length);
//oZipStream.Flush();
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
oZipStream.Finish();
oZipStream.Close();
oZipStream.Dispose();
}
HttpContext.Current.Response.OutputStream.Flush();
HttpContext.Current.Response.End();
}
Everything is fine, unless when number of files get big.
My question:
Is there a way to initiate the download (let the download manager on client side popup), and then start writing on the stream?
I monitored w3wp.exe (IIS) process, and it seems that the data is being written on memory instead of Stream. When w3wp.exe memory usage riches a certain number, it releases the memory and nothing happens (no download).
Thank you in advance.
Have you tried using this?
HttpContext.Current.Response.BufferOutput = false;
As far as I know, you cannot stream it while archiving. You need to zip them first, then stream it. As the result, server is finally out of memory if the final zip is extremely large.
What I end up doing is I write it to a temporary zip file then stream that temporary file.

Categories