c# - Physical path given, virtual path expected in Server.MapPath - c#

I trying to change my directory which in my local c disk, but where errors says in the title. Is there any way aside from using Server.MapPath?. I'm using a ZipOutputStream nuget package.
I want to locate my directory in C: instead inside the project folder.
public FileResult DownloadZipFileSig(string FileId){
var fileName = "FilesDL".zip";
var tempOutPutPath = Server.MapPath(Url.Content("C:/Users/SDILAP2/Desktop/ID_Esig_Files")) + fileName;
using (ZipOutputStream s = new ZipOutputStream(System.IO.File.Create(tempOutPutPath)))
{
s.SetLevel(9);
byte[] buffer = new byte[4096];
List<string> stringList = FileId.Split(',').ToList();
List<string> tempList = new List<string>();
foreach (string str in stringList)
{
if (System.IO.File.Exists(Server.MapPath("C:/Users/SDILAP2/Desktop/ID_Esig_Files/" + str + ".jpeg")))
{
tempList.Add(Server.MapPath("C:/Users/SDILAP2/Desktop/ID_Esig_Files/" + str + ".jpeg"));
}
}
stringList = tempList;
for (int i = 0; i < stringList.Count; i++)
{
ZipEntry entry = new ZipEntry(Path.GetFileName(stringList[i]));
entry.DateTime = DateTime.Now;
entry.IsUnicodeText = true;
s.PutNextEntry(entry);
using (FileStream fs = System.IO.File.OpenRead(stringList[i]))
{
int sourceBytes;
do
{
sourceBytes = fs.Read(buffer, 0, buffer.Length);
s.Write(buffer, 0, sourceBytes);
} while (sourceBytes > 0);
}
}
s.Finish();
s.Flush();
s.Close();
}
return File(finalResult, "application/zip", fileName);
}

You might be not quite grasping how web URL's work, and how server.mappath() is to be used.
Web users:
When you have a web based url, then all html markup in a page, or even user supplied URL's are so called web based.
So, if you have a folder from the root of your web site say called MyUpLoads
Then that is just a folder in the web site path names.
eg:
www.mywebsite/UpLoadFiles/cat.jpg
And if you write html markup, then you can and could provide a URL to the above picute, or say with a html image control, you could set the ImageURL or "source" (src) to that file.
And if you using IIS (and not IIS express), then of course you can add what is called a virutal folder. Say some big server drive on ANOHTER computer on the same network.
So, that virtual folder could be anywhere on your network, and of course AGAIN for web HTML, or web URL's, again you use this format:
www.mysite/MassiveFolder/info.pdf
or maybe
localhost:5403/MyUpLoads/cat.jpg
However, in code behind?
ANY code behind (c# or vb.net) ALWAYS uses plane jane WINDOWS file paths.
These are valid full windows file names.
That means that code behind is 100% free to open/read/use/see/play with ANY file on the computer, and any file even on the computer network.
So when you use
server.mapPath("localhost:5403/MyUpLoads/cat.jpg")
Then the above is translated into a local plane jane DOS/WINDOWS file path!!!!
The above may well become
C:\Users\AlbertKallal\source\repos\CSharpWebApp\MyUpLoads\cat.jpg
So keep in mind:
web urls - HTML/asp markup in a page = web based syntax/path.
computer path: plane jane full path names like all windows software.
So, in your case?
var fileName = "FilesDL".zip";
var tempOutPutPath = #"C:/Users/SDILAP2/Desktop/ID_Esig_Files")) + fileName;
So you don't need nor want to user server.mappath, since that is ONLY for a given HTML or web based URL that you want to translate into the local computer file path system.
Since your path name(s) are already in that format, then no need is required.
in fact, keep in mind that you can use this fact to your advantage.
ANY folder (or a vitural folder) will appear in your valid URL's and path names (web based).
However, you might have some pdf's, or sensitive documents. So move that folder OUT of the root or web project folders.
Now, no valid URL's exist, or are even allowed.
However, code behind? It can run, see and use ANY file on your computer - and you use code behind to get those files - but the web site, web side of things has NO ability to use or see or get those files. And you can still do things like say provide a download button, but your code behind can fetch the file, read it and pump it out to the end user (stream the file).
So you only need (have) to use the Server.MapPath function WHEN the URL comes from the web site or html markup. This will translate that web based URL into a regular good old fashion full qualified windows file path name.
However, if you already have that full windows path name, then no URL translate to windows file path is required.
So, for the most part, your code behind can look at, see, grab and play with files on the server. Web users, or web based urls MUST be part of the folders in the web site, but no such restrictions exist for the code behind.
Now, when the code is deployed to a web server, often some file security rights on in place, but as a general rule, that web code behind is NOT limited nor restricted to JUST folders in the web site. Those valued URL's are a restriction for the users and web browsers, and as noted, often a folder outside of the web site is used for security purposes, since no possible valid web based paths can use/see or even resolve to file outside of the root starting folder of the web site.
So for those existing files, you don't need server.mappath.

Related

Downloading images from publicly shared folder on Dropbox

I received a link to shared folder from e-commerce company. The link is public and not shared with my dropbox account directly.
How do I get an url to the image that I can pass to either DownloadAsync method of the same sdk or simply HttpClient and well ... download it?
Ideally it would be the same link I get when I click on the image when viewing that shared folder in a browser.
https://www.dropbox.com/sh/{folder_hash}/{file_hash_maybe}/{filename}?dl=0
This is what I have tried:
using Dropbox.Api;
using Dropbox.Api.Files;
...
var accessToken = "abracadabra";
var sharedFolderUrl = "https://www.dropbox.com/sh/{folder_hash}?dl=0";
using (var dbx = new DropboxClient(accessToken))
{
var sharedLink = new SharedLink(sharedFolderUrl);
var sharedFiles = await dbx.Files.ListFolderAsync(path: "", sharedLink: sharedLink);
// sharedFiles - has over 13,000 entries, I use cursor to get them all.
foreach (var file in sharedFiles.Entries)
{
if (file.IsFile)
{
// tried this, but:
// 1. it's crazy to loop through all
// 2. link.Response.Url gives me the same url to a shared folder for all items
var link = await dbx.Sharing.GetSharedLinkFileAsync(url: sharedFolderUrl, path: "/" + file.Name);
}
}
}
Using the GetSharedLinkFileAsync method is the right way to programmatically download a file from a shared link. It actually gives both the metadata (in the link.Response in your code like you mentioned), as well as the file data directly (not via a URL).
To access the file data, you can use any of the GetContentAs... methods documented under IDownloadResponse as returned by GetSharedLinkFileAsync. In your code, that would look something like: link.GetContentAsStreamAsync() (or whichever one you want).
Alternatively, if you want to download the entire folder from the shared link, you can use the URL parameters documented in this help center article. (That may fail for very large folders though.)

Not allowed to load local resource from App_Data folder

I need to server a larger amount of Pdf's which require authorisation in order to be able to download.
I have read that it is advisable to place them in the App_Data folder.
I have created three folders in the App_Data folder:
> SetOne
> SetTwo
> SetThree
I need to pass these files to my view.
Controller
var files = Directory.EnumerateFiles(Server.MapPath("~/App_Data/SetOne"));
return View(files);
View
<ul>
#foreach (var fullPath in Model)
{
var fileName = Path.GetFileName(fullPath);
var downloadPath = #Path.GetDirectoryName(fullPath) + "\\" + #fileName;
<li>#fileName</li>
}
</ul>
Using the above code, I am able to list the contents of the SetOne folder in an unordered list, however when I attempt to view one of the Pdf's I see:
Not allowed to load local resource:
file:///B:/Development/MyProject/MyProject.Web/App_Data/SetOne/sampleOne.pdf
How can I allow the application to give access to these files?
edit
I've also tried creating a new folder called Pdfs and moving the documents to this, however I get the same error message when I view in chrome dev tools.
Do I need to implement a Http Handler for this task?
Your approach is OK for WinForms application but shouldn't work for Web. downloadPath should contain the Url but not the physical path on the file (like some.com/pdfs/1.pdf)
You could use Server.MapPath for this case

Converting a local folder structure to a folder structure on a server

I'm currently playing around with Paths in .Net and have run into some difficultly with regards to replicating a local folder structure passed as a string from a web service to my site running under localhost on IIS Express.
Essentially, our users will select an image within our desktop software, the local path of which will be sent as a property of the image in our web service. So, when my script accesses the web service, it is fed a string such as:
C:\\Users\\axumadmin\\Pictures\\axumImages\\Countries\\Canada\\canadianFlag.jpg
What our users will then do is FTP this folder structure to a specified directory on our server:
ServerRoot\\umbraco\\axumImages\\Countries\\Canada\\canadianFlag.jpg
The main issue I have here is that I cannot seem to modify the path retreived from the web service to only return the directories from axumImages downwards. So in essence, my local path would be converted to:
axumImages\\Countries\\Canada\\canadianFlag.jpg
I have already tried playing with System.IO.Path to convert this path into the format that I wish to be returned but ultimately all I have acheived so far is either retreiving just the image filename:
canadianFlag.jpg
System.IO.Path.GetFileName(image.FileName);
or the parent directory of the image
C:\\Users\\axumadmin\\Pictures\\axumImages\\Countries\\Canada
Therefore my question is, how can I parse the string so that it is only using axumImages and its descendants?
Any help would be greatly appreciated.
use string.Substring
var startIndex = image.FileName.IndexOf("axumImages");
string test = image.FileName.Substring(startIndex, image.FileName.Length-startIndex)
I ended up solving this in the end using string parsing.
string test = image.FileName.Split(new[] { "axumImages" }, StringSplitOptions.None)[1];
In this example, image.Filename is my filename. So if the filename is:
C:\\Users\\axumadmin\\Pictures\\axumImages\\Countries\\Canada\\canadianFlag.jpg
this will return
\\Countries\\Canada\\canadianFlag.jpg
I can then concatenate this into a usable variable below which then amounts to the path I require:
var actualPath = "axumImages" + "test";

How to display image which is stored on Local drive or network drive?

I have a asp page in which i have to display the image which is stored in my local disk C: and in some cases from network drive
Example path:--C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg
I have done the following code in c# code behind
Image image = new Image();
image.Height = 150;
image.Width = 150;
string path = #"C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg";//this path will come from database dynamically this is for test only
image.ImageUrl = path;
this.Controls.Add(image);
but image is not showing up so i stumbled upon the this SO Question and i updated my code as below
for page which is showing image
Image image = new Image();
image.Height = 150;
image.Width = 150;
string path = #"C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg";
image.ImageUrl = "ImageWriter.aspx?path=" + path;
this.Controls.Add(image);
and for proxy page
Response.ContentType = "image/jpeg"; // for JPEG file
string physicalFileName = Request.QueryString["path"];
Response.WriteFile(physicalFileName);
this is working fine but i have two question
1) Why the file is accessible from the physical path while proxy from page but other page cannot able to access it ?
2) And is there any other way to do it ?
Any help would be great thanks.
The images are not available because that path has no relative context to an asp.net site user through a browser who will probably be on another PC and network. To fix this, all you need to do is create an ASHX handler page that fetches the images that are on the server's local drive or network and serve them as an image to the browser:
public void ProcessRequest(HttpContext context)
{
string imgName = context.Request.QueryString["n"];
context.Response.ContentType = "image/png";
string path = #"C:\Users\Public\Pictures\Sample Pictures\" + imgName;
Image image = Image.FromFile(path);
image.Save(context.Response.OutputStream, ImageFormat.Png);
}
And then in your asp just point an image url to the ashx:
image.src = "images.ashx?n=penguin.jpg";
1) Why the proxy page can access the physical path but other page cannot able to access it ?
The other page can. However, the other page isn't accessing the file. It's just setting the file's path to the HTML output for the client (web browser) to access it. Resulting in this:
<img src = "C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg" />
Since the user doesn't have access to that file, the img tag won't work. The purpose of the "proxy" page is to serve the content of the file from a location which the user can access, that location being the proxy page.
2) And is there any other way to do it ?
Nope. Either the user has to have direct access to the file via some virtual path on the web server, or you have to have a proxy which reads the file's contents and sends it to the user. It has little to do with your C# code and everything to do with what the user can see on the web server. Unless the file is in a web-accessible folder, the user can't see it.
This is a very common and standard approach to securing files behind a web application. Sometimes, for example, you want to check the user's authorization before allowing them to see a file. If the file were publicly accessible, they could just go to it directly. But if there's a proxy page between the user and the file then that page can enforce authorization.
On my experience, the best way, just to avoid all the security problem that finally make impossible the above solutions, is to setup a local website and set the image url like this: image1.ImageUrl="http://pcname/photofolder/myphoto1.png".
pcname is the name of the local web server and the path is the path of a virtual directory set in the local IIS. To setup a local IIS is very simple, google have tons of tips, and to setup a virtual directory is only needed to enter the iis, open the default website, right-clik on "add a new virtual directory" and set the name (photofolder in my example) and make it point to a physical local disk folder and the trick is done. This has also a vantage, that's to say that you can access that folder in all clients connected to the lan.

How to upload specific folders with login system in ASP.NET?

I will create an ASP.NET Web Application like this;
Users can login their own username and password.
Users can file upload their own folder (I define the folders manually), and also they can see all files in their own page and they can download them.
I think I can use an architecture like this;
I should use ASP.NET Login Controls, we all agree with that. But I also should use C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe and ASP.NET Web site Administration Tool? What does exactly aspnet_regsql.exe do? What does Administration Tool do? They are (Login controls + aspnet_regsql.exe + Administration Tool) only I need for creating a user login system?
For file upload I think to use File Upload control. Then, For example; if I have a user "A", folder should be like http://ourserver/A. I have no idea how can I upload file to specific folder. And how can I show to users their own uploaded files? (Also users should download them) Is there any asp.net control for doing this ?
EDIT: I prefer step by step explanation rather than giving some code. I want to also understand what these applications are doing ?
1) If you run the regsql tool, it will popup a screen asking for some sql information and then create a set of tables relative to membership etc. If you start a basic MVC 3 application, it comes with an account controller, login, logout, forgot password all wired up. This talks to that database. Your alternative is to create a custom membership provider, there are lots of tutorials out there for doing that. You can control more things with the custom membership provider, but it's a bit more work.
2) AmRans example code is perfect for saving the actual file. As far as the folder for the given user goes, then I would probably configure a base directory in your web.config, then;
if( Directory.Create( Path.Combine( baseDirectory, UserDirectory)).Exists) {
}
although if you're using .NET 2, then that might remain;
string savePath = Path.Combine( baseDirectory, UserDirectory);
Directory.Create( savePath );
if( Directory.Exists( savePath)) {
}
For viewing of those files, if the user is logged in, you can query the save directory + username and list out all the files in that.
See the code below , not the exact but might be help for you. Here UploadTypes is a custom enum and userId is the current user logged in , id (primary key of the table or any thing that is unique), with control name, passed from Front end.
/// <summary>
/// returns the virtual application path of uploaded file.
/// </summary>
/// <param name="fu"></param>
/// <param name="uploadType"></param>
/// <returns></returns>
public static string GetAppFileUploadPath(FileUpload fu, UploadTypes uploadType, int userId)
{
var path = string.Format("~/Images/no.gif");
if (fu.HasFile)
{
if (fu.FileContent.Length > 0)
{
var filename = Path.GetFileNameWithoutExtension(fu.PostedFile.FileName);
var extension = Path.GetExtension(fu.PostedFile.FileName);
switch (uploadType)
{
case UploadTypes.Images:
_validExtensions = new List<string>
{
".bmp", ".jpg",".jpeg",".gif",".png"
};
if (_validExtensions.Contains(extension.ToLower()))
{
var newFileName = string.Format("{0}_{1}_{2}{3}", filename, userId, Guid.NewGuid().ToString().Substring(0, 5), extension);
var serverUploadPath = string.Format("{0}/VirtualOffice/Uploads/ProductImage/{1}", HttpRuntime.AppDomainAppPath, newFileName);
path = string.Format("~/VirtualOffice/Uploads/ProductImage/{0}", newFileName);
fu.SaveAs(serverUploadPath);
}
else
{
Common.ShowMessage("Only image files allowed, bmp, jpg , gif or png.");
}
break;
case UploadTypes.Documents:
_validExtensions = new List<string>
{
".doc", ".rtf",".docx",".pdf",".txt"
};
if (_validExtensions.Contains(extension.ToLower()))
{
var newFileName = string.Format("{0}_{1}_{2}{3}", filename, userId, Guid.NewGuid().ToString().Substring(0, 5), extension);
var serverUploadPath = string.Format("{0}/VirtualOffice/Uploads/ProductImage/{1}", HttpRuntime.AppDomainAppPath, newFileName);
fu.SaveAs(serverUploadPath);
path = string.Format("~/VirtualOffice/Uploads/ProductImage/{0}", newFileName);
}
else
{
Common.ShowMessage("Only valid text files allowed, doc, docx ,rtf, pdf or txt.");
}
break;
}
}
}
return path;
}
This is my custom file upload code to allow either image or document as per scenario.
First of all, before jumping on to what controls to use, whether to create a Website project or ASP.Net MVC3 application, I think its crucial to understand what your core design should be. Implementing the GUI aspect of login is easy, what is important is the backend piece of it.
How do you authenticate users? What role should they have (read only, write only, read/write etc). What mode should you choose and how do you configure your site to accept one of these forms of authentication. If you have an understanding of these, you can skip this, otherwise I would suggest reading up here: ASP.NET authentication and authorization and this: ASP.NET 2.0 Membership, Roles, Forms Authentication, and Security Resources
Now the file upload and management part - well, while its fun to do things on your own from a learning perspective, I also believe in not reinventing the wheel (if it suits your purpose of course). There are good open source projects that you can benefit from like this:
http://www.codeproject.com/KB/aspnet/WebFileManager.aspx (created by Jeff Atwood and has a good explanantion)
http://www.filemanager.3ntar.net/
http://www.ajaxfilebrowser.com/
Hope this helps.
In File upload you can check user after login than check the folder is exist or not by using:
Directory.Exist("FolderPath")
If it is exist upload to that folder other wise you can create folder using
Directory.Create("Folder Path and Name");
Then upload file to that folder
Note that because of security purpose, you might have to provides writting rights to NETWORK SERVICE on you server for each folder you want to upload in. Because of that, I'll recommand you to create a folder in your root directory or anywhere you want and provide write access to this folder, say FolderA. So, any child folder will have same rights.
Also, there's plenty controls that can handle files from the web. Unfortunaly, most of them cost something (if you want one stable and who's working great). One we bought and work great for us, is this one (CuteWebUI.AjaxUploader). It allows you to specify many file at once or not, use Flash, IFrame or AJAX as you want it, save temporaly file automaticaly, etc.
Good luck!
Note : I talk french, so sorry for my english

Categories

Resources