I have been stuck on saving the virtual path of a file upload to my db. Without the virtual path the file is being saved and the url in the db is the physical path of the file. so when i try to download it I am getting the local resource not allowed. the url starts with file:///C:path....
When i use break points I see that the physical path is being changed to the virtual path, however it exceptions out.
apiController
//POST
public async Task<HttpResponseMessage> Post()
{
try
{
//saving the posted file to the harddisk
string root = HttpContext.Current.Server.MapPath("~/Files/");
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
//Get Logged in User Name
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var user = manager.FindById(User.Identity.GetUserId());
//getting the user details and storing in the object
Document model = new Document();
model.TypeId = Convert.ToInt32(provider.FormData["TypeId"]);
model.TypeName = provider.FormData["TypeName"];
model.PipeName = provider.FormData["PipeName"];
model.DocumentUrl = provider.FormData["DocumentUrl"];
model.DocumentUrl = model.DocumentUrl == "" ? null : model.DocumentUrl;
//if there is a file then save that file to the desired location
if (provider.FileData.Count > 0)
{
MultipartFileData fileData = provider.FileData[0];
FileInfo fi = new FileInfo(fileData.LocalFileName);
if (!Directory.Exists(fi.DirectoryName))
{
Directory.CreateDirectory(fi.DirectoryName);
}
else
{
//getting the file saving path
string clientFileName = fileData.Headers.ContentDisposition.FileName.Replace(@"""", "");
if (clientFileName != "")
{
string clientExtension = clientFileName.Substring(clientFileName.LastIndexOf('.'));
string space = ("-");
var dt = model.DocumentDate.ToString("y").Replace('/', '-').Replace(':', '-');
var CompanyName = model.CompanyName.Replace('_', ' ');
string vPath = root.Replace(@"C:\Development\TransparentEnergy\TransparentEnergy", "~").Replace("\\", "/");
string serverFileName = vPath + CompanyName + space + model.TypeName + space + model.CounterPartyName + space + dt + clientExtension;
model.DocumentUrl = serverFileName;
FileInfo fiOld = new FileInfo(vPath);
if (fiOld.Exists)
fiOld.Delete();
//if (File.Exists())
fi.MoveTo(serverFileName);
}
else
{
if (fi.Exists)
fi.Delete();
}
}
}
//calling DB to save the user details
using (var context = new ApplicationDbContext())
{
//save to db
context.Documents.Add(model);
context.SaveChanges();
}
}
catch (Exception fex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, fex);
}
//sending the confirmation or error back to the user
return Request.CreateResponse(HttpStatusCode.OK);
}
The breakpoint at :
model.DocumentUrl = serverFileName;
shows
"~/Files/Black Elk-Invoices-None-May 2006.pdf"
The Exception happens here
FileInfo fiOld = new FileInfo(vPath);
if (fiOld.Exists)
fiOld.Delete();
//if (File.Exists())
fi.MoveTo(serverFileName);
The FiloInfo(vPath) shows
~/Files/
The Exception happens at :
fi.MoveTo(serverFileName);
Exception message:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.__Error.WinIOError() at System.IO.FileInfo.MoveTo(String destFileName) at TransparentEnergy.ControllersAPI.apiInvoiceController.d__0.MoveNext() in c:\Development\TransparentEnergy\TransparentEnergy\ControllersAPI\SubmitApi\apiInvoiceController.cs:line 87
Updated
//POST
public async Task<HttpResponseMessage> Post()
{
try
{
//saving the posted file to the harddisk
string root = HttpContext.Current.Server.MapPath("~/Files/");
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
//Get Logged in User Name
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var user = manager.FindById(User.Identity.GetUserId());
//getting the user details and storing in the object
Document model = new Document();
model.TypeId = Convert.ToInt32(provider.FormData["TypeId"]);
model.TypeName = provider.FormData["TypeName"];
model.LocationId = Convert.ToInt32(provider.FormData["LocationId"]);
model.LocationName = provider.FormData["LocationName"];
model.PipeId = Convert.ToInt32(provider.FormData["PipeId"]);
model.PipeName = provider.FormData["PipeName"];
model.CompanyId = Convert.ToInt32(provider.FormData["CompanyId"]);
model.CompanyName = provider.FormData["CompanyName"];
model.PlantId = Convert.ToInt32(provider.FormData["PlantId"]);
model.PlantName = provider.FormData["PlantName"];
model.CounterPartyId = Convert.ToInt32(provider.FormData["CounterPartyId"]);
model.CounterPartyName = provider.FormData["CounterPartyName"];
string docDate = provider.FormData["DocumentDate"];
model.DocumentDate = DateTime.Parse(docDate.Trim('"'));
model.UploadedBy = user.Name;
model.UploadDate = DateTime.Now;
model.DocumentUrl = provider.FormData["DocumentUrl"];
//if there is a file then save that file to the desired location
if (provider.FileData.Count > 0)
{
MultipartFileData fileData = provider.FileData[0];
FileInfo fi = new FileInfo(fileData.LocalFileName);
//getting the file saving path
string clientFileName = fileData.Headers.ContentDisposition.FileName.Replace(@"""", "");
if (clientFileName != "")
{
string clientExtension = clientFileName.Substring(clientFileName.LastIndexOf('.'));
string dash = ("-");
var dt = model.DocumentDate.ToString("y").Replace('/', '-').Replace(':', '-');
var CompanyName = model.CompanyName.Replace('_', ' ');
string vPath = root.Replace(@"C:\Development\TransparentEnergy\TransparentEnergy", "~").Replace("\\", "/");
string path = String.Format(CompanyName + dash + model.TypeName + dash + model.CounterPartyName + dash + dt + clientExtension);
string combination = Path.Combine(vPath, path);
model.DocumentUrl = combination;
FileInfo fiOld = new FileInfo(path);
if (fiOld.Exists)
fiOld.Delete();
//if (File.Exists())
fi.MoveTo(vPath);
}
else
{
if (fi.Exists)
fi.Delete();
}
}
//calling DB to save the user details
using (var context = new ApplicationDbContext())
{
//save to db
context.Documents.Add(model);
context.SaveChanges();
}
}
catch (Exception fex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, fex);
}
//sending the confirmation or error back to the user
return Request.CreateResponse(HttpStatusCode.OK);
}
This Works!
public async Task<HttpResponseMessage> Post()
{
try
{
//saving the posted file to the harddisk
//string root = HttpContext.Current.Server.MapPath("~/Files/");
string root = HostingEnvironment.MapPath(ConfigurationManager.AppSettings["~/Files/"]);
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
//Get Logged in User Name
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var user = manager.FindById(User.Identity.GetUserId());
//getting the user details and storing in the object
Document model = new Document();
model.TypeId = Convert.ToInt32(provider.FormData["TypeId"]);
model.TypeName = provider.FormData["TypeName"];
model.LocationId = Convert.ToInt32(provider.FormData["LocationId"]);
model.LocationName = provider.FormData["LocationName"];
model.PipeId = Convert.ToInt32(provider.FormData["PipeId"]);
model.PipeName = provider.FormData["PipeName"];
model.CompanyId = Convert.ToInt32(provider.FormData["CompanyId"]);
model.CompanyName = provider.FormData["CompanyName"];
model.PlantId = Convert.ToInt32(provider.FormData["PlantId"]);
model.PlantName = provider.FormData["PlantName"];
model.CounterPartyId = Convert.ToInt32(provider.FormData["CounterPartyId"]);
model.CounterPartyName = provider.FormData["CounterPartyName"];
string docDate = provider.FormData["DocumentDate"];
model.DocumentDate = DateTime.Parse(docDate.Trim('"'));
model.UploadedBy = user.Name;
model.UploadDate = DateTime.Now;
model.DocumentUrl = provider.FormData["DocumentUrl"];
//if there is a file then save that file to the desired location
if (provider.FileData.Count > 0)
{
MultipartFileData fileData = provider.FileData[0];
FileInfo fi = new FileInfo(fileData.LocalFileName);
//getting the file saving path
string clientFileName = fileData.Headers.ContentDisposition.FileName.Replace(@"""", "");
if (clientFileName != "")
{
string clientExtension = clientFileName.Substring(clientFileName.LastIndexOf('.'));
var dt = model.DocumentDate.ToString("y").Replace('/', '-').Replace(':', '-');
var CompanyName = model.CompanyName.Replace('_', ' ');
string vPath = root.Replace(@"C:\Development\TransparentEnergy\TransparentEnergy", "~").Replace("\\", "/");
string fileName = String.Format("{0}-{1}-{2}-{3}{4}", CompanyName, model.TypeName, model.CounterPartyName, dt, clientExtension);
string combination = Path.Combine(vPath, fileName);
model.DocumentUrl = combination;
string physicalPath = HttpContext.Current.Server.MapPath("/Files");
string relativePath = Path.Combine(physicalPath, fileName);
FileInfo fiOld = new FileInfo(relativePath);
if (fiOld.Exists)
fiOld.Delete();
//if (File.Exists())
fi.MoveTo(relativePath);
}
else
{
if (fi.Exists)
fi.Delete();
}
}
//calling DB to save the user details
using (var context = new ApplicationDbContext())
{
//save to db
context.Documents.Add(model);
context.SaveChanges();
}
}
catch (Exception fex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, fex);
}
//sending the confirmation or error back to the user
return Request.CreateResponse(HttpStatusCode.OK);
}
I suspect your issue happens because the (badly named) serverFileName
in fi.MoveTo(serverFileName);
actually points to a virtual path instead of to a physical path.
Note that I'd really advise to rethink your code. Some examples:
string space = ("-");
: "-" isn't a space.model.DocumentDate.ToString("y").Replace('/', '-').Replace(':', '-');
looks like a bad way to format a date.string serverFileName = vPath + CompanyName + space + model.TypeName + space + model.CounterPartyName + space + dt + clientExtension;
First, use Path.Combine to join a folder and a filename. Second, wouldn't it be better to use string.Format
to create the name of the file instead of a long concatenation? Third, serverFileName
is IMHO a bad name, I'd call this a path.model.DocumentUrl
: first it gets the value of provider.FormData["DocumentUrl"]
, then you check if model.DocumentUrl
is an empty string (note that it is preferred to use string.Empty
) and set it to NULL if that's the case, and then you assign it serverFileName
.