How do I properly auto append to filename if file exist - c#

Here is what I have tried, please note that lblImageAlt.Text property has been set to 'Images/'
string ImgPath1 = lblImageAlt1.Text.ToString();
string ImgPath2 = lblImageAlt2.Text.ToString();
string ImgPath3 = lblImageAlt3.Text.ToString();
string filename1 = "";
string filename2 = "";
string filename3 = "";
if (fileuploadimages1.HasFile)
{
if (File.Exists(Server.MapPath(ImgPath1 + filename1)))
{
string extension = Path.GetExtension(filename1);
string name = Path.GetFileNameWithoutExtension(filename1);
int fileMatchCount = 1;
while (File.Exists(Server.MapPath(ImgPath1 + name + "(" + fileMatchCount + ")" + extension)))
fileMatchCount++;
fileuploadimages1.SaveAs(Server.MapPath(ImgPath1 + name + "(" + fileMatchCount + ")" + extension));
}
else
{
fileuploadimages1.SaveAs(Server.MapPath(ImgPath1 + filename1));
}
}
else
{
filename1 = "noImage.jpg";
}
but the same image does not get a number appended to it. What am I doing wrong here?

Path.GetFileName returns the whole filename with the extension.
Thus your code is checking if a file exists with a name like this:
image.jpg1
You should change the code to split the filename in two parts, the base filename and the extension, then check if the filename exists and then rebuild the filename from its parts adding the increment number until you find a non existant filename
// Extract just the filename from the posted file removing the path part (image.jpg)
filename1 = Path.GetFileName(fileuploadimages1.PostedFile.FileName);
baseFile = Path.GetFileNameWithoutExtension(fileuploadimages1.PostedFile.FileName);
extension = Path.GetExtension(fileuploadimages1.PostedFile.FileName);
int fileMatchCount = 1;
// Check if a file with the given name exists in the Images1 subfolder of the root folder of your site
while(File.Exists(Server.MapPath(Path.Combine(ImgPath1, filename1)))
{
// The given file exists already, so we now need to build
// a different (but related) filename using a counter....
// This will create a filename like 'image(001).jpg'
// and then we will restart the loop
fileName1 = string.Format("{0}({1:D3}){2}", baseFile, fileMatchCount, extension);
// ... but first increment the counter in case even the new name exists
fileMatchCount++;
}
// We exit the loop with a name that should not exists in the destination folder
fileuploadimages1.SaveAs(Server.MapPath(Path.Combine(ImgPath1, filename1));

You're not actually modifying filename1. You're checking if it ends in a (0), (1), etc. and incrementing your index, but never actually modifying the variable.

Try using
if(File.Exists(Server.MapPath(ImgPath1 + filename1)))
{
string extension = Path.GetExtension(filename1);
string name = Path.GetFileNameWithoutExtension(filename1);
int fileMatchCount = 1;
while(File.Exists(Server.MapPath(ImgPath1 + name + "(" + fileMatchCount + ")" + extension)))
fileMatchCount++;
fileuploadimages1.SaveAs(Server.MapPath(ImgPath1 + name + "(" + fileMatchCount + ")" + extension));
}
else
fileuploadimages1.SaveAs(Server.MapPath(ImgPath1 + filename1));

Related

error : The given path's format is not supported

Getting this error The given path's format is not supported. at this line
System.IO.Directory.CreateDirectory(visit_Path);
Where I am doing mistake in below code
void Create_VisitDateFolder()
{
this.pid = Convert.ToInt32(db.GetPatientID(cmbPatientName.SelectedItem.ToString()));
String strpath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
String path = strpath + "\\Patients\\Patient_" + pid + "\\";
string visitdate = db.GetPatient_visitDate(pid);
this.visitNo = db.GetPatientID_visitNo(pid);
string visit_Path = path +"visit_" + visitNo + "_" + visitdate+"\\";
bool IsVisitExist = System.IO.Directory.Exists(path);
bool IsVisitPath=System.IO.Directory.Exists(visit_Path);
if (!IsVisitExist)
{
System.IO.Directory.CreateDirectory(path);
}
if (!IsVisitPath)
{
System.IO.Directory.CreateDirectory(visit_Path);\\error here
}
}
getting this value for visit_Path
C:\Users\Monika\Documents\Visual Studio 2010\Projects\SonoRepo\SonoRepo\bin\Debug\Patients\Patient_16\visit_4_16-10-2013 00:00:00\
You can not have : in directory name, I suggest you to use this to string to get date in directory name:
DateTime.Now.ToString("yyyy-MM-dd hh_mm_ss");
it will create timestamp like:
2013-10-17 05_41_05
additional note:
use Path.Combine to make full path, like:
var path = Path.Combine(strpath , "Patients", "Patient_" + pid);
and last
string suffix = "visit_"+visitNo+"_" + visitdate;
var visit_Path = Path.Combine(path, suffix);
In general always use Path.Combine to create paths:
String strPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
String path = Path.Combine(strPath,"Patients","Patient_" + pid);
string visitdate = db.GetPatient_visitDate(pid);
this.visitNo = db.GetPatientID_visitNo(pid);
string fileName = string.Format("visit_{0}_{1}", visitNo, visitdate);
string visit_Path = Path.Combine(path, fileName);
bool IsVisitExist = System.IO.Directory.Exists(path);
bool IsVisitPath=System.IO.Directory.Exists(visit_Path);
To replace invalid characters from a filename you could use this loop:
string invalidChars = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
foreach (char c in invalidChars)
{
visit_Path = visit_Path.Replace(c.ToString(), ""); // or with "."
}
You can't have colons : in file paths
You can't use colons (:) in a path. You can for example Replace() them with dots (.).
Just wanted to add my two cents.
I assigned the path from a text box to string and also adding additional strings, but I forgot to add the .Text to the text box variable.
So instead of
strFinalPath = TextBox1.Text + strIntermediatePath + strFilename
I wrote
strFinalPath = TextBox1 + strIntermediatePath + strFilename
So the path became invalid because it contained invalid characters.
I was surprised that c# instead of rejecting the assignment because of type mismatch, assigned invalid value to the final string.
So look at the path assignment string closely.

Autoincrement end of filename if previous set of files exist

I need to create x number of files (a set) but I must first check to see if the files exist with a similar name.
For example, tiftest1.tif, tiftest2.tif, ... exist and I must write tiftest again to the same directory. I'd like to append _x to the end of the filename, where x is a number that is auto-incremented, each time that I want to create the set. So I can have tiftest1_1.tif,tiftest2_1.tif, tiftest1_2.tif, tiftest2_2.tif, tiftest1_3.tif, tiftest2_3.tif and so forth.
Here is what I have so far:
...
DirectoryInfo root = new DirectoryInfo(fileWatch.Path);
FileInfo[] exist = root.GetFiles(fout + "*.tif");
if (exist.Length > 0)
{
int cnt = 0;
do
{
cnt++;
DirectoryInfo root1 = new DirectoryInfo(fileWatch.Path);
FileInfo[] exist1 = root.GetFiles(fout + "*" + "_" + cnt + ".tif");
arg_proc = "-o " + "\"" + fileWatch.Path
+ "\\" + fout + "%03d_" + cnt + ".tif\" -r " + "\"" + openDialog.FileName + "\"";
} while (exist1.Length > 0); //exist1 is out of scope so this doesn't work
}
else
{
arg_proc = "-o " + "\"" + fileWatch.Path
+ "\\" + fout + "%03d.tif\" -r " + "\"" + openDialog.FileName + "\"";
}
...
exist1.length is out of scope so the loop will continually run. I'm not certain how to correct this. My method was to originally scan the directory for a match and see if the length of the array is greater than 0. If it is > 0 then the _x will autoincrement until a match isn't found. arg_proc is a string used in a function (not included) which will create the files.
Can't you just reuse your exist variable?
FileInfo[] exist = root.GetFiles(fout + "*.tif");
if (exist.Length > 0)
{
int cnt = 0;
do
{
cnt++;
DirectoryInfo root1 = new DirectoryInfo(fileWatch.Path);
exist = root.GetFiles(fout + "*" + "_" + cnt + ".tif");
arg_proc = "-o " + "\"" + fileWatch.Path + "\\"
+ fout + "%03d_" + cnt + ".tif\" -r " + "\"" + openDialog.FileName + "\"";
} while (exist.Length > 0);
}
...
This way, exist won't be out of scope. It didn't look like you needed the original list of files once you started incrementing your counter, so if that is the case, you can just keep reusing exist to count your existing filenames.

check for duplicate filename when copying files in C#

I want to copy files to a directory and rename to a particular format. but if the filename already exists, it should append {1}, {2} or {3} before the file extension.
My code renamed and copied the file and named it to my desired format say filename.pdf, when it checked for duplicate it renamed it to filename1.pdf. but when it tried copying again, it gave an error "file already exists" but i wanted it to have named it to filename02.pdf.
Pls can someone help me out.
Here is the code i have written so far.
{
string fileSource, filesToCopy, target, nextTarget;
string sourceDir = #"C:\HCP_PDFs";
string destinationDir = #"C:\RenamedHcpPdfs";
DirectoryInfo di = new DirectoryInfo(destinationDir);
// create the directory if it dosnt exist
if (!Directory.Exists(destinationDir))
{
Directory.CreateDirectory(destinationDir);
}
foreach (string myFiles in lstBoxFilenames.Items)
{
filesToCopy = myFiles;
fileSource = Path.Combine(sourceDir, filesToCopy);
//Extract only HCP Name by splitting , removing file Extension and removing HCP ID
string hcp = filesToCopy.Split('_')[0];
string hcpCd = filesToCopy.Split('_')[1];
string hcpID = filesToCopy.Split('_')[2];
string hcpName = String.Format((filesToCopy.Split('_')[3]).Replace(".pdf", ""));
//combine the HCP ID, HCP name and date
target = Path.Combine(destinationDir, hcp + "{" + hcpCd + "~" + hcpID + "}" + hcpName + "{2013_03_14}" + ".pdf");
// if file exists in directory then rename and increment filename by 1
int i = +1 ;
nextTarget = Path.Combine(destinationDir, hcp + "{" + hcpCd + "~" + hcpID + "}" + hcpName + "{2013_03_14}" + i + ".pdf");
if (File.Exists(target))
{
File.Copy(fileSource, nextTarget);
break;
}
//if file does not exist, rename
else
{
File.Copy(fileSource, target);
}
}
}
Try this :
string target = Path.Combine(destinationDir, hcp + "{" + hcpCd + "~" + hcpID + "}" + hcpName + "{2013_03_14}.pdf");
while(File.Exists(target))
{
i++;
target = Path.Combine(destinationDir, hcp + "{" + hcpCd + "~" + hcpID + "}" + hcpName + "{2013_03_14}" + i + ".pdf");
}
File.Copy(fileSource, target);
break;
Do this
while(File.Exists(target))
{i++;}
now declare your target path.

Moving folder from one location to another in a web service

I have a web service that locates files in a folder (C:\Incoming) and emails them to a specified email address. I want to be able to move that folder, once it has been mailed to another folder (C:\Processed).
I tried using this code below, but it does not work.
string SourceFile = "C:\\Incoming\\" + "" + Year + "" + Month + "" + Day + "";
string destinationFile = "C:\\Processed" + "" + Year + "" + Month + "" + Day + "";
System.IO.File.Move(SourceFile , destinationFile);
I get an error saying that the sourcefile could not be found. I have verified that it does exist and I have access to it.
You are moving folders not file you will need to iterate over files to copy one by one.
string Source = "C:\\Incoming\\" + "" + Year + "" + Month + "" + Day + "";
string destination = "C:\\Processed" + "" + Year + "" + Month + "" + Day + "";
DirectoryInfo di = new DirectoryInfo(Source);
FileInfo[] fileList = di.GetFiles(".*.");
int count = 0;
foreach (FileInfo fi in fileList)
{
System.IO.File.Move(Source+"\\"+fi.Name , destinationFile+"\\"+fi.Name);
}
Use String.Format for one, second use System.IO.File.Exists() to make sure the file is there.
string SourceFile = String.Format("C:\\Incoming\\{0}{1}{2}",Year,Month,Day);
string destinationFile = String.Format("C:\\Processed\\{0}{1}{2}",Year,Month,Day);
if (System.IO.File.Exists(SourceFile) {
System.IO.File.Move(SourceFile , destinationFile);
}

Getting "The process cannot access the file because it is being used by another process" when saving multiple files from the request stream

I am using the HTML5 canvas element and the new HTML5 file i\o function to drop multiple files on it and have them upload. It works fine, but now I need to generate a new filename if no files are in the destination directory (It's a 7 digit integer) or get the name of the last uploaded file, convert it to int32 and increment that by one for every new file being uploaded to the same directory. This is where the GetFileName(dir); comes in. The first image always uploads fine but the problem begins once the second file is saved and the process hits ImageJob.Build(), I presume this is because once the new file is starting to write, the GetFile() method runs for second file in line simultaneously and is checking for last written file, which is still being written and this creates the conflict. How can I fix this, maybe I can somehow itterate with a foreach over the Request.InputStream data or implement some kind process watch that waits for the process to finish?
Update: I tried using TempData to store the generated filename, and just increment on the int value in TempData for all the next file names and it appears to do better, gets more images in but still errors at some point. But TempData is not for that as it gets erased after each read, reassigning to it again does not help. Maybe I'll try storing it in session.
The process cannot access the file 'C:\Users\Admin\Documents\Visual Studio
2010\Projects\myproj\myproj\Content\photoAlbums\59\31\9337822.jpg'
because it is being used by another process.
public PartialViewResult Upload()
{
string fileName = Request.Headers["filename"];
string catid = Request.Headers["catid"];
string pageid = Request.Headers["pageid"];
string albumname = Request.Headers["albumname"];
var dir = "~/Content/photoAlbums/" + catid + "/" + pageid + "/" + (albumname ?? null);
var noex = GetFileName(dir);
var extension = ".jpg";
string thumbFile = noex + "_t" + extension;
fileName = noex + extension;
byte[] file = new byte[Request.ContentLength];
Request.InputStream.Read(file, 0, Request.ContentLength);
string imgdir;
string thumbimgdir;
string imageurl;
if (albumname != null)
{
imgdir = Server.MapPath("~/Content/photoAlbums/" + catid + "/" + pageid + "/" + albumname + "/" + fileName);
thumbimgdir = Server.MapPath("~/Content/photoAlbums/" + catid + "/" + pageid + "/" + albumname + "/" + thumbFile);
imageurl = "/Content/photoAlbums/" + catid + "/" + pageid + "/" + albumname + "/" + thumbFile;
}
else
{
imgdir = Server.MapPath("~/Content/photoAlbums/" + catid + "/" + pageid + "/" + fileName);
thumbimgdir = Server.MapPath("~/Content/photoAlbums/" + catid + "/" + pageid + "/" + thumbFile);
imageurl = "/Content/photoAlbums/" + catid + "/" + pageid + "/" + thumbFile;
}
ImageJob b = new ImageJob(file, imgdir, new ResizeSettings("maxwidth=1024&maxheight=768&format=jpg")); b.CreateParentDirectory = true; b.Build();
ImageJob a = new ImageJob(file, thumbimgdir, new ResizeSettings("w=100&h=100&mode=crop&format=jpg")); a.CreateParentDirectory = true; a.Build();
ViewBag.CatID = catid;
ViewBag.PageID = pageid;
ViewBag.FileName = fileName;
return PartialView("AlbumImage", imageurl);
}
public string GetFileName(string dir)
{
var FullPath = Server.MapPath(dir);
var dinfo = new DirectoryInfo(FullPath);
string FileName;
if (dinfo.Exists)
{
var Filex = dinfo.EnumerateFiles().OrderBy(x => x.Name).LastOrDefault();
FileName = Filex != null ? Path.GetFileNameWithoutExtension(Filex.Name) : null;
if (FileName != null)
{
FileName = FileName.Contains("_t") ? FileName.Substring(0, FileName.Length - 2) : FileName;
int fnum;
Int32.TryParse(FileName, out fnum);
FileName = (fnum + 1).ToString();
if (fnum > 999999) { return FileName; } //Check that TryParse produced valid int
else
{
var random = new Random();
FileName = random.Next(1000000, 9999000).ToString();
}
}
else
{
var random = new Random();
FileName = random.Next(1000000, 9999000).ToString();
}
}
else
{
var random = new Random();
FileName = random.Next(1000000, 9999000).ToString();
}
return FileName;
}
You simply cannot use the Random class if you want to generate unique filenames. It uses the current time as the seed, so two exactly concurrent requests will always produce the same 'random' number.
You could use a cryptographic random number generator,
but you would still have to ensure that (a) only one thread would generate it at a time, and (b) you used a sufficiently long identifier to prevent the Birthday paradox.
Thus, I suggest that everyone use GUID identifiers for their uploads, as they solve all of the above issues inherently (I believe an OS-level lock is used to prevent duplicates).
Your method also doesn't handle multiple file uploads per-request, although that may be intentional. You can support those by looping through Request.Files and passing each HttpPostedFile instance directly into the ImageJob.
Here's a simplified version of your code that uses GUIDs and won't encounter concurrency issues.
public PartialViewResult Upload()
{
string albumname = Request.Headers["albumname"];
string baseDir = "~/Content/photoAlbums/" + Request.Headers["catid"] + "/" + Request.Headers["pageid"] + "/" (albumname != null ? albumname + "/" : "");
byte[] file = new byte[Request.ContentLength];
Request.InputStream.Read(file, 0, Request.ContentLength);
ImageJob b = new ImageJob(file, baseDir + "<guid>.<ext>", new ResizeSettings("maxwidth=1024&maxheight=768&format=jpg")); b.CreateParentDirectory = true; b.Build();
ImageJob a = new ImageJob(file, baseDir + "<guid>_t.<ext>", new ResizeSettings("w=100&h=100&mode=crop&format=jpg")); a.CreateParentDirectory = true; a.Build();
//Want both the have the same GUID? Pull it from the previous job.
//string ext = PathUtils.GetExtension(b.FinalPath);
//ImageJob a = new ImageJob(file, PathUtils.RemoveExtension(a.FinalPath) + "_t." + ext, new ResizeSettings("w=100&h=100&mode=crop&format=jpg")); a.CreateParentDirectory = true; a.Build();
ViewBag.CatID = Request.Headers["catid"];
ViewBag.PageID = Request.Headers["pageid"];
ViewBag.FileName = Request.Headers["filename"];
return PartialView("AlbumImage", PathUtils.GuessVirtualPath(a.FinalPath));
}
If the process is relatively quick (small files) you could go in a loop, check for that exception, sleep the thread for a couple of seconds, and try again (up to a maximum number of iterations). One caveat is that if the upload is asynchronous you might miss a file.
A couple of other suggestions:
Make the GetFileName to be a private method so that it doesn't get triggered from the web.
The OrderBy in the Filex query might not do what you expect once the it goes to 8 digits (possible if the first Random() is a very high number).
The Random() should probably be seeded to produce better randomness.

Categories

Resources