Save file in a folder above the site files - asp.net

My host has the following structure:
/Web -> Where is the content of the site
/Data -> Folder permissions to read and write
How do I upload a file to the Data folder?
The code below does not work, since "~" returns the directory / web.
//Save Image
var serverPath = Server.MapPath(Href("~/Data/") + id);
Directory.CreateDirectory(serverPath);
imgOri.Save(Path.Combine(serverPath, fileName));

Server.MapPath() is designed to map a path up to the root directory of the application. As you are trying to upload a file above the root it won't work.
You can upload a file above the root by specifying the exact file path (if the host can provide it):
var serverPath = "C:\YourFolder\Data\") + id);
I'm surprised your host is allowing you to upload a file outside of the root directory as there are a number of dangers in doing this...you may also run into Trust issues.

You can obtain the path to a directory which sits at the same level of your site root by using Server.MapPath as below:
#{
var root = Server.MapPath(".");
var temp = root.Split('\\');
temp[temp.Length - 1] = "Data";
var newpath = string.Join("\\", temp);
}
Hosting companies used to provide "data" directories outside of the root folder as a safe place for things like Access mdb databases. You cannot directly browse to a directory which is outside of the root of your site. ASP.NET did away with the need for these things with the introduction of App_Data. The only reason you would want to use this kind of folder nowadays is if you want to apply some kind of authentication prior to serving the contents of the directory. Then you need to use a handler, or a simple cshtml file will do. You can combine the WebSecurity helper with the WebImage helper to first authenticate the user, and then retrieve and display the image if they pass the test. The src in your img tag will point to the cshtml file, with a querystring or UrlData value so you know which image to display.
If you don't need to validate users prior to displaying image, storing the image files outside of the root adds an unnecessary level of complication.

Related

How to retrieve asp.net media / resources based on logged in user?

I have an asp.net web api project using token based authentication. my app uploaded and retrieve images and I keep file path in table_myfiles along with the uploaded user ID.
I would like the user to access only the files he have uploaded, which I can identify from the table.
How to protect my resources to restrict access to only to the user based on table_myfile ? And not to anyone without logging in or direct link / path ?
I have been searching for any possible solution for a week now , I think I should implement a middleware to manage access. But I couldn’t find any resources on how to implement the same.
Currently my api shows all resources just by directly accessing the file path/link.
The simple apporach is to remove the vitural folder, or that folders from the web site folders. That way, no simple URL exists for any of the files.
So, for a user to get/see/use/download a file? You present say a listview or some kind of grid (or repeater) that displays and lists out the files.
Then, when they want to download or view a file?
You use response.write and stream the file down to the client side.
Remember, on the server, code behind uses 100% clean and correct windows file paths. For any web based URL, then that folder must be in a valid path of the web site. When they type in a valid URL, it eventually gets translated to that given folder in the site (or a external folder provided when you create a mapped "virtual" folder in IIS. However, if you don't provide that virtual folder, or the folder is NOT in the web site file/folder sets, then no valid URL's exist. However, that folder can be directly used and hit with code behind - any valid server path/folder name is allowed in code behind.
Because when streaming the file, you need path name, file name, AND ALSO the "mine" type. Thankfully, .net 4.5 or later has this ability.
so, from a database (table) I display the file names like this:
But, if you click on the preview image, that is a image button.
The code behind simply gets/grabs the file name from the database.
I then download (stream) the file to the browser side like this:
if (File.Exists(strInternalFullPath))
{
string strConType = MimeMapping.GetMimeMapping(strInternalFullPath);
binFile = File.ReadAllBytes(strInternalFullPath);
Response.ContentType = strConType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(strWebUrl));
Response.BinaryWrite(binFile);
Response.End();
}
else
MyToast2(this, btnLink.ClientID.ToString, "File Not found", "We no longer have this file avaiable.");
so, this buttion behaves 100% like a link, but there are no existing URL's or path name that points to the files folder from a web based URL.
Remember:
Web based URLs - they auto map from the web site URL to a existing folder.
You can use server.MapPath("some url to file") to "translate" this to a internal file name.
Code based files:
In your .net code (code behind) ANY file name is a standard plane, jane file name that points to a file on the server.
so, once we have that file name from the database, you can steam the file as if the user clicked on a link. But you never have to expose the actual file name, or file path. And no such valid URL's exist on the web site, since you do NOT have that files folder in the web site folder hierarchy - but placed that folder outside of the web site.
As long as that folder is outside of the web folders, and as long as you don't setup a virtual folder that points to that folder outside the web folders?
Then code behind can STILL get/grab/see/use any file on the server. that code uses a full valid windows file name, - but the web site will have no mapping to such a folder - hence no valid URL's will exist or can be typed in.

Where should I save files dynamically generated by the ASP.NET Web API?

My ASP.NET Web API service dynamically generates files for users to download.
The remote application sends a request to the API which:
Generates the file and saves it ----> where?? <-----
Returns the URL of the file location so it can be downloaded.
Nothing fancy there, but my question is what are the best practices for where to save these files?
Some digging around suggests that App_Data might be the appropriate place but I haven't seen anything definitive.
Some considerations:
This all happens on a company intranet so security isn't really a big deal.
The files are essentially temporary. Is there a simple way to delete the file once it's downloaded? Not a big deal - I can set up a scheduled task to clean out whatever the destination folder is.
Thanks!
You can write to any location your application stores data in.
I recommend using the system Temp directory, that's what it's there for (System.IO.Path.GetTempPath()) or if your have write access, a subdirectory of your application:
String path = Server.MapPath("~/Temp");
if( !Directory.Exists( path ) ) Directory.CreateDirectory( path );
using(FileStream fs = File.OpenWrite( Path.Combine( path, "TempFileName.dat" ) )) {
fs.Write( new Byte[1024] );
}
If you have access to your web server, you could also create a virtual directory under your web application and configure it to point to whatever file location you want. Then you can have your application save the files into that virtual directory using System.IO. That's what I've done in the past.

download link give me filenotfound exception

in my controller, this is the code i have
public FileResult Download(string file)
{
var vFullFileName = HostingEnvironment.MapPath("~/App_Data/Files/");
var files = uploadedfileRepository.AllIncluding();
string filename = (from f in files
select f.FileName).First();
return File(Path.Combine(vFullFileName, filename), "application/csv", filename);
}
I put the breakpoint and the file point to the right directory, but why still give me File not found exception?
and in my view this is what i have
<td>
#Html.ActionLink("Download", "Download", new { id = item.FileName})
</td
Your action method have a parameter with name file. But your are HTML will have a parameter/ query string called id, instead od file, So change your view code to
#Html.ActionLink("Download", "Download", new { file= item.FileName})
Also to get the path, try this
string fullFilePath=Path.Combine(Server.MapPath("~/App_Data"),filename)
return File(fullFilePath,"application/csv",filename);
App_Data is for database files that are accessed by MS SQL Server, and possibly your application's own data files (like a Lucene index).
IIS (and ASP.NET) are configured to block any client requests to that directory.
The solution is just to move the files to another directory. Just create a new folder in your site's root (say "CsvFiles") and link to that.
That said, why don't you serve up a HTTP 301 Redirection (or even a direct link) to the CSV files instead of serving them via your application?
UPDATE: This answer is incorrect because by serving the file contents via an MVC File response the user's browser doesn't acutally access the App_Data directory.

Collect path from database and show image with <img> tag in ASP.NET C#

I'm saving file paths in database. Suppose an image file path, which is out of the project source folder. Collecting this path with the FileUpload Control. Next, reading this path from database into string like
string path=#dr["image"].ToString();
Now wanna show this image with the html image tag.
new_main.InnerHtml = "<img src=\"" + path + "\" alt=\"image\" /> ";
It's not working. Checked in net,but nothing is working for me yet.Any idea about solution? Thanks in advance.
You need to use the relative path instead of using physical path.suppose you have hosted website in d:\Websites\Testsite\ then it is physical path and you access it by giving url http://yourdomain/Testsite/first.html then this is virtual path you have to give linkimage and path a virtual path.
You can access the files within the website folder or you can make virtual directory of folders outside you website folder and access it through virtual directory. This article explains you have to make a virtual directory
Suppose you have website folder d:\websites\Testsite and you want to access files within d:\Data\Testfile.jpg, make a virtual directory in side TestWebsite pointing to d:\Data and access files within it through virual directory.
your image path is not relative it should be like eg. ~/Images/myimage.png insted of D:\data\myimage.png . If your image path is relative then try this example
string Path="~/Images/myimage.png";
new_main.InnerHtml = string.Format(#"<a href='{0}'><img src='{1}' alt='image' /> </a>",Path);

Programmatically retrieving IIS log file location in an ASP.NET application

I'm trying to determine the location of the IIS log file location of my ASP.NET application. I tried WMI, but wasn't able to find it. Any suggestions?
Note: I want to be able to retrieve the location programmatically; inside my application for further use.
Edit: Here's my code: This works but does not give me the actual physical directory location of the logs. So this is basically useless.
ManagementPath p2=new ManagementPath("IIsLogModule.Name='logging/Microsoft IIS Log File Format'");
ManagementObject log = new ManagementObject(scope, p2, objectGet);
log.Get();
logPath.Text = log["__PATH"].ToString();
On IIS7 you could use Microsoft.Web.Administration assembly, Site class has a property named LogFile, you can get various info about log file for site, for example log file directory can be obtained with this code:
ServerManager manager = new ServerManager();
Site mySite = manager.Sites["SiteName"];
Response.Write("Log file directory : " + mySite.LogFile.Directory + "\\W3svc" + mySite.Id.ToString());
I don't like very much that hardcoded part with directory prefix for site, but didn't find any other better way
You should able to use ADSI (or WMI) to do that - browse IIS metabase and look for 'LogFileDirectory' property for the web site node. For example,
var root = new DirectoryEntry(#"IIS://localhost/W3SVC");
var sites = root.Children;
foreach(DirectoryEntry site in sites) {
var name = site.Properties["ServerComment"][0];
var logFile = site.Properties["LogFileDirectory"][0];
}
Disclaimer: Untested code
See this powershell example using similar idea.

Resources