Reputation: 3785
I have made a view that takes a file upload and my controller has a http post method that basically saves the path in the db and then saves the file within the app_data dir. However, I want to make sure the file doesnt over write another file. I.e. if another files exists, rename it. I know I could do this in 2 ways, either by ensuring all file names are unique with guid or by renaming the file. I have tried the second approach, but my methodology seems cumbersome. I would appreciate it if anyone can advise on if there is another approach:
here is what I have:
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName); //Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), fileName);
if (System.IO.File.Exists(path))
{
for (int i = 1; true; i++)
{
path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), (fileName + "_" + i));
if (!System.IO.File.Exists(path))
{
break;
}
}
}
file.SaveAs(path);
model.Image = path;
}
Upvotes: 0
Views: 739
Reputation: 1195
Try this:
if (file != null && file.ContentLength > 0)
{
var extension = Path.GetExtension(file.FileName)
var fileName = Path.GetFileNameWithoutExtension(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), fileName);
for (int i = 1; System.IO.File.Exists(path); i++)
path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), fileName + "_" + i.ToString() + extension);
file.SaveAs(path);
model.Image = path;
}
Happy to Help you!
Upvotes: 1
Reputation: 2136
hopefully this works for you:
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var fullFileName = fileName + "_" + Date.Now.ToString("yyyyMMdd_hhss")
path = Path.Combine(Server.MapPath("~/App_Data/uploads/slides"), fullFileName );
file.SaveAs(path);
model.Image = path;
}
Upvotes: 1
Reputation: 26434
First of all, don't check if exists, it does not help you in any way, because a file may get added before your following lines execute. You want to have a Try...Catch
block instead. And you need to actually create a file, not just return a path, which did not exist at some point of execution.
Second, separate your logic of creating a file from your MVC, so code like Server.MapPath
and model.Image = path;
would be somewhere else.
Third, timestamp sounds like the best option here, just make sure you include milliseconds. If not enough you can include partial checksum at the end, whichever approach makes it unique. You still need to have code in place that checks uniqueness, even if it would rarely happen, and just regenerate file name again, maybe wait 50ms, to make sure it will be a different file name.
Upvotes: 2