I can not upload any file today!
I said "today" because it was working yesterday. I did not change anything that might be related to that.
I always get this error:
Could not find a part of the path
It is worth mentioning that every configuration is declared in program file.
My Uploader method:
public string Upload(IFormFile? file, string path, string fileToRemove = "")
{
if (file == null)
return "";
var directoryPath = $"{_webHostEnvironment.WebRootPath}/{path}";
if (!Directory.Exists(directoryPath))
Directory.CreateDirectory(directoryPath);
var fileName = $"{DateTime.Now.ToFileTime()}-{file.FileName}";
var filePath = $"{directoryPath}/{fileName}";
using var stream = File.Create(filePath);
file.CopyTo(stream);
if (!string.IsNullOrEmpty(fileToRemove) ||
!string.IsNullOrWhiteSpace(fileToRemove))
{
var fileToRemovePath = $"{_webHostEnvironment.WebRootPath}/{fileToRemove}";
if (File.Exists(fileToRemovePath))
File.Delete(fileToRemovePath);
}
return $"{path}/{fileName}";
}
I have an Azure App (.Net 4.5) and I have some static files stored on the filesystem that I want to read from, but I get a System.UnauthorizedAccessException like so
string template = string.Empty;
var file = HostingEnvironment.MapPath("~/App_Data/EmailTemplates/" + fileName);
if (!string.IsNullOrEmpty(file))
{
template = File.ReadAllText(file); <-- Unauthorized Access Exception Here
}
return template;
I know the best practice is Azure Storage, but how do I make this work this way?
As File.ReadAllText states about UnauthorizedAccessException, it could be caused by one of the following conditions:
path specified a file that is read-only.
-or-
This operation is not supported on the current platform.
-or-
path specified a directory.
-or-
The caller does not have the required permission.
You could leverage kudu console and use Attrib command to check the attributes for your files or directories. Also, you could try to use TYPE command to display the contents of your file or click the Edit button from the file list table as follows:
Also, I created a new web app and deployed my MVC application for displaying the files under the App_Data folder, it could work as expected, you could refer to it.
UPDATE:
//method for getting files
public List<DownLoadFileInformation> GetFiles()
{
List<DownLoadFileInformation> lstFiles = new List<DownLoadFileInformation>();
DirectoryInfo dirInfo = new DirectoryInfo(HostingEnvironment.MapPath("~/App_Data"));
int i = 0;
foreach (var item in dirInfo.GetFiles())
{
lstFiles.Add(new DownLoadFileInformation()
{
FileId = i + 1,
FileName = item.Name,
FilePath = dirInfo.FullName + #"\" + item.Name
});
i = i + 1;
}
return lstFiles;
}
//action for downloading a file
public ActionResult Download(string FileID)
{
int CurrentFileID = Convert.ToInt32(FileID);
var filesCol = obj.GetFiles();
string fullFilePath = (from fls in filesCol
where fls.FileId == CurrentFileID
select fls.FilePath).First();
string contentType = MimeMapping.GetMimeMapping(fullFilePath);
return File(fullFilePath, contentType, new FileInfo(fullFilePath).Name);
}
UPDATE2:
public ActionResult ViewOnline(string FileID)
{
int CurrentFileID = Convert.ToInt32(FileID);
var filesCol = obj.GetFiles();
string fullFilePath = (from fls in filesCol
where fls.FileId == CurrentFileID
select fls.FilePath).First();
string text = System.IO.File.ReadAllText(fullFilePath);
return Content(text);
}
I'm working on MVC5 project on .NET 4.5.3. I have View with #Html.BeginForm and FormMethod.Post this view calls [HttpPost] ActionResult. In the Controller i get necessary ID's from the submitted form and then pass them for exporting.
[HttpPost]
public ActionResult PrepareForExport()
{
ExportService export = new ExportService();
if (Request.Form["button"] != null)
{
string selected = Request.Form["button"].ToString();
export.GeneratePdf(ptoRequestsService.GetByID(Convert.ToInt32(selected)));
}
else if (Request.Form["toExport"] != null)
{
List<PtoRequest> ptoListForExport = new List<PtoRequest>();
string selectedItems = Request.Form["toExport"].ToString();
string[] selectedList = selectedItems.Split(',');
foreach (var pto in selectedList)
{
ptoListForExport.Add(ptoRequestsService.GetByID(Convert.ToInt32(pto)));
}
export.GenerateZip(ptoListForExport);
}
return RedirectToAction("Requests" + LoggedUser.ID);
}
And in the ExportService class i have this export method.
public void GenerateZip(List<PtoRequest> approvedPtos)
{
byte[] pdfContent = null;
string dateFormat = "yyyy-MM-dd";
string filePath = null;
if (!Directory.Exists(HttpContext.Current.Server.MapPath(#"~/Files/PdfFiles/")))
{
Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/Files/PdfFiles/"));
filePath = HttpContext.Current.Server.MapPath("~/Files/PdfFiles/");
}
else
{
filePath = HttpContext.Current.Server.MapPath("~/Files/PdfFiles/");
}
foreach (var Pto in approvedPtos)
{
pdfContent = FillPdfTemplate(Pto);
string fileName = Pto.User.FirstName + " " + Pto.User.LastName + "_" + Pto.StartDate.ToString(dateFormat) + ".pdf";
string fileDirectory = filePath + fileName;
using (FileStream fs = new FileStream(fileDirectory, FileMode.OpenOrCreate))
{
fs.Write(pdfContent, 0, pdfContent.Length);
}
}
string zipName = String.Format("Report_{0}.zip", DateTime.Now.ToString("yyyy-mm-dd-HHmmss"));
string zipFile = filePath + zipName;
using (ZipFile zip = new ZipFile())
{
zip.AddDirectory(filePath);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.BufferOutput = false;
HttpContext.Current.Response.ContentType = "application/zip";
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + zipName);
zip.Save(HttpContext.Current.Response.OutputStream);
HttpContext.Current.Response.Write(zip.ToString());
HttpContext.Current.Response.End();
Directory.Delete(filePath, true);
}
}
Everything works fine, but when my method complete the job i got exception with code 500. I do my googling to understand my problem and it is something like this 1. I understand that the problem is in HttpHeader but did not understand how to solve it in my case. Then i tried the solution with if (!Response.IsRequestBeingRedirected) but i still got this exception. After this I tried to return ZipFile from GenerateZip Method and instead calling Response in ExportService class to call it at Controller, but i still got this Error. I have an idea to remove [HttpPost] attribute and to take my ID's in other way but my point is to do it that way. Can anyone point me in any direction to solving this? What is the right decision, where should i call Response for this case, is it option to write jQuery script to prevent submitting form in .cshtml?
You are calling HttpContext.Current.Response.End(); in your GenerateZip method and then attempting to Redirect the user in the ControllerAction. This is causing your "Headers cannot be written after response is sent" error. Instead of that, return a byte array or Stream object (FileStream?) from the GenerateZip method and return a FileResult in the Action. Redirecting the user after the file download can (only?) be achieved using JavaScript. Here is an example. How to return a FileResult AND RedirectToAction in ASP.NET MVC
public ActionResult GeneratePdf(int id)
{
var labelRepository = new LabelRepository();
var label = labelRepository.GetLabel(id);
if (String.IsNullOrEmpty(label.PDFLocation))
{
var action = Url.Content("~/Label/ViewPdf/" + id); //doc
Doc theDoc = new Doc();
string filename = Guid.NewGuid().ToString();
string path = Server.MapPath("~/" + filename + ".pdf");
theDoc.AddImageUrl("action");
theDoc.Save(path);
theDoc.Clear();
label.PDFLocation = path;
labelRepository.Save();
return base.File(path, "application/pdf");
}
else
{
return base.File(label.PDFLocation, "application/pdf");
}
}
This won't add my image url so my pdf won't open up so I can see it. Any ideas?-
In the example here, a complete URL is being passed to the AddImageUrl() function, not a fragment of an URL, as your example shows.
Perhaps you need a call to RouteUrl() so that you can get a complete Url to pass to your AddImageUrl() method?
I have this method for grabbing the file name from a string URI. What can I do to make it more robust?
private string GetFileName(string hrefLink)
{
string[] parts = hrefLink.Split('/');
string fileName = "";
if (parts.Length > 0)
fileName = parts[parts.Length - 1];
else
fileName = hrefLink;
return fileName;
}
You can just make a System.Uri object, and use IsFile to verify it's a file, then Uri.LocalPath to extract the filename.
This is much safer, as it provides you a means to check the validity of the URI as well.
Edit in response to comment:
To get just the full filename, I'd use:
Uri uri = new Uri(hreflink);
if (uri.IsFile) {
string filename = System.IO.Path.GetFileName(uri.LocalPath);
}
This does all of the error checking for you, and is platform-neutral. All of the special cases get handled for you quickly and easily.
Uri.IsFile doesn't work with http urls. It only works for "file://".
From MSDN : "The IsFile property is true when the Scheme property equals UriSchemeFile."
So you can't depend on that.
Uri uri = new Uri(hreflink);
string filename = System.IO.Path.GetFileName(uri.LocalPath);
Most other answers are either incomplete or don't deal with stuff coming after the path (query string/hash).
readonly static Uri SomeBaseUri = new Uri("http://canbeanything");
static string GetFileNameFromUrl(string url)
{
Uri uri;
if (!Uri.TryCreate(url, UriKind.Absolute, out uri))
uri = new Uri(SomeBaseUri, url);
return Path.GetFileName(uri.LocalPath);
}
Test results:
GetFileNameFromUrl(""); // ""
GetFileNameFromUrl("test"); // "test"
GetFileNameFromUrl("test.xml"); // "test.xml"
GetFileNameFromUrl("/test.xml"); // "test.xml"
GetFileNameFromUrl("/test.xml?q=1"); // "test.xml"
GetFileNameFromUrl("/test.xml?q=1&x=3"); // "test.xml"
GetFileNameFromUrl("test.xml?q=1&x=3"); // "test.xml"
GetFileNameFromUrl("http://www.a.com/test.xml?q=1&x=3"); // "test.xml"
GetFileNameFromUrl("http://www.a.com/test.xml?q=1&x=3#aidjsf"); // "test.xml"
GetFileNameFromUrl("http://www.a.com/a/b/c/d"); // "d"
GetFileNameFromUrl("http://www.a.com/a/b/c/d/e/"); // ""
The accepted answer is problematic for http urls. Moreover Uri.LocalPath does Windows specific conversions, and as someone pointed out leaves query strings in there. A better way is to use Uri.AbsolutePath
The correct way to do this for http urls is:
Uri uri = new Uri(hreflink);
string filename = System.IO.Path.GetFileName(uri.AbsolutePath);
I think this will do what you need:
var uri = new Uri(hreflink);
var filename = uri.Segments.Last();
using System.IO;
private String GetFileName(String hrefLink)
{
return Path.GetFileName(hrefLink.Replace("/", "\\"));
}
THis assumes, of course, that you've parsed out the file name.
EDIT #2:
using System.IO;
private String GetFileName(String hrefLink)
{
return Path.GetFileName(Uri.UnescapeDataString(hrefLink).Replace("/", "\\"));
}
This should handle spaces and the like in the file name.
As of 2020, handles query strings & encoded URLs
public static string GetFileNameFromUrl (string url)
{
var decoded = HttpUtility.UrlDecode(url);
if (decoded.IndexOf("?") is {} queryIndex && queryIndex != -1)
{
decoded = decoded.Substring(0, queryIndex);
}
return Path.GetFileName(decoded);
}
this is my sample you can use:
public static string GetFileNameValidChar(string fileName)
{
foreach (var item in System.IO.Path.GetInvalidFileNameChars())
{
fileName = fileName.Replace(item.ToString(), "");
}
return fileName;
}
public static string GetFileNameFromUrl(string url)
{
string fileName = "";
if (Uri.TryCreate(url, UriKind.Absolute, out Uri uri))
{
fileName = GetFileNameValidChar(Path.GetFileName(uri.AbsolutePath));
}
string ext = "";
if (!string.IsNullOrEmpty(fileName))
{
ext = Path.GetExtension(fileName);
if (string.IsNullOrEmpty(ext))
ext = ".html";
else
ext = "";
return GetFileNameValidChar(fileName + ext);
}
fileName = Path.GetFileName(url);
if (string.IsNullOrEmpty(fileName))
{
fileName = "noName";
}
ext = Path.GetExtension(fileName);
if (string.IsNullOrEmpty(ext))
ext = ".html";
else
ext = "";
fileName = fileName + ext;
if (!fileName.StartsWith("?"))
fileName = fileName.Split('?').FirstOrDefault();
fileName = fileName.Split('&').LastOrDefault().Split('=').LastOrDefault();
return GetFileNameValidChar(fileName);
}
Usage:
var fileName = GetFileNameFromUrl("http://cdn.p30download.com/?b=p30dl-software&f=Mozilla.Firefox.v58.0.x86_p30download.com.zip");
Simple and straight forward:
Uri uri = new Uri(documentAttachment.DocumentAttachment.PreSignedUrl);
fileName = Path.GetFileName(uri.LocalPath);
//First Method to get fileName from fileurl
List<string> fileNameListValues = new List<string>();
//fileNameListValues List consist of fileName and fileUrl
//we need to get fileName and fileurl from fileNameListValues List
name
foreach(var items in fileNameListValues)
{
var fileUrl = items;
var uriPath = new Uri(items).LocalPath;
var fileName = Path.GetFileName(uriPath);
}
//Second Way to get filename from fileurl is ->
fileNameValue = "https://projectname.com/assets\UploadDocuments\documentFile_637897408013343662.jpg";
fileName = " documentFile_637897408013343662.jpg";
//way to get filename from fileurl
string filename =
fileNameValue.Substring(fileNameValue.LastIndexOf("\\") + 1);