How to download a file from my webserver to my desktop? - c#

I have looked around the internet for 3 hours now looking for a solution to my problem and I'm starting to wonder if anyone else has ever had this exact problem?
I am using IIS7 to host a website that does some local things around our office. Well, developing the site everything worked fine, but now that I am hosting the site I cannot (and neither can anyone else for that matter) click on the link to download the file that is needed. (lets just pretend they click on a link to download some random file from the webserver)
Well, it fails downloading the file from what I can guess as being a permissions error. I have looked for a solution but cannot seem to find one. I know very little about IIS7 so I do not understand very much about the Application Pool Identity stuff, although I did manage to grant full access for that identity to the file/folders. Anyways, here is the specific area it is messing up on..
This is a piece of the default.cshtml page that calls a Function from a .cs file:
//well.. pretty close to the exact thing, just got rid of a bunch of unecessary junk
#{
string tmp = Functions.downloadFile(fileName)
}
<html>
tmp
</html>
This is the part of the .cs file that actually downloads the file to the desktop
public static string downloadFile(string fileName) //i know this example doesnt
//use filename, but the original code does.
{
if (Directory.Exists("C:\WebSite\thingsToDownload"))
{
string[] files = Directory.GetFiles("C:\WebSite\thingsToDownload");
foreach (string s in files)
{
string[] tmp = s.Split('\\');
try
{
File.Copy(s,
Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
+ "\\" + tmp[tmp.Length - 1]);
}
catch (Exception e)
{
return "ERROR COPYING: " + e.Message;
}
}
return "GOOD";
}
return "DIRECTORY DOESNT EXIST";
}
After that is all said and done, i get "ERROR COPYING: Access to the path '\fileName' is denied.
My Guess is that the webserver does not have access to the person's desktop in order to put the files there.
If anyone can shed some light and help me get this it would be greatly appreciated!

If you want to download a file by clicking a link you should use response.
Here's a sample you can use for example when a user clicks a link or button or something:
const string fName = #"C:\picture.bmp";
FileInfo fi = new FileInfo(fName);
long sz = fi.Length;
Response.ClearContent();
Response.ContentType = Path.GetExtension(fName);
Response.AddHeader("Content-Disposition", string.Format("attachment; filename = {0}",System.IO.Path.GetFileName(fName)));
Response.AddHeader("Content-Length", sz.ToString("F0"));
Response.TransmitFile(fName);
Response.End();

It worked when you developed it, because it was running on your computer and thus had access to your desktop. There is no such thing as download to desktop. You can serve files and let the user decide where to save the file; on the desktop or elsewhere. But you have to do this over http, not directly from the server.

Related

FileUpload works well locally but not well as I publish the project to the server

I've developed a web app using asp.net c#. There is a FileUpload Control that may upload pdf or word file. But as I published the website, it is not working properly! While on the local version no problem seen. I've been trying the following:
if (FileUpload1.PostedFile != null)
{
string fn = System.IO.Path.GetFileName(empDL.client_id + FileUpload1.PostedFile.FileName);
if (FileUpload1.PostedFile.ContentLength > 0)
{
FileUpload1.PostedFile.SaveAs(Path.Combine(Server.MapPath("~/Documents/" + fn)));
empDL.uploadedfile = fn;
}
}
Maybe it is because that Documents folder hasn't write permission, you can set every one permission for this folder and try again.
Try this,
First make sure you have created your folder (although the code also checks for that) and you have permission to access that folder.
string Fileloc = "/" + "Content/Upload/YourFolder/";
if (FileUpload1.PostedFile!=null)
{
if (!System.IO.Directory.Exists(Fileloc))
{
System.IO.Directory.CreateDirectory(Fileloc);
}
var path = Path.Combine(HttpContext.Current.Server.MapPath(Fileloc), FileUpload1.PostedFile.FileName);
FileUpload1.PostedFile.SaveAs(path);
}
let me know if it has solved your problem or not.

Can anyone figure out a way to navigate a directory using this FTP Client?

So I downloaded an FTP Client from code project, but I cannot figure out a way to navigate through the directories. The project link is at the bottom of the post.
Anyways, I am logging on to an FTP server with the following information
ServerIP: ftp.swfwmd.state.fl.us
Username: anonymous
Password: youremail#gmail.com
I need to navigate to the "pub" folder (i.e. it's the only folder where I have permission to write, delete, rename, make directories, etc), but there is no way to click on a directory and traverse said directory.
For reference, the directories look as such:
README
lost+found
pub
public
...etc
I want to be able to click on the pub folder and see everything in pub. I'm not sure if this was originally implemented in the project, but I want to be able to do this.
To accomplish navigating through the pub folder, I was thinking something along the lines of...
ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://ftp.randomSite/text.txt");
However, I have zero experience with GUI and don't exactly know how to get this working when a user clicks on one of the directories listed above.
If someone could take a look at the project and figure out a way to traverse the directories using the GUI, I would be greatly indebted.
**EDIT: **
So I've tried the following:
FtpWebRequest reqFTP;
try
{
ListBox b1 = (ListBox)sender;
reqFTP = (FtpWebRequest)WebRequest.Create("ftp://" + ftpServerIP + "/" + b1.Text);
which gives me the correct uri ftp://ftp.swfwmd.state.fl.us/pub (I verified this in the watch window), but I am guessing the code below is suspect.
It throws an exception immediately when it tries to get the response. I have no idea why as everything looks fine.
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
ftpStream.Close();
response.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
//Update current directory
btnLstFiles_Click(sender, e);
which gives me the current
Link to Project
http://www.codeproject.com/Articles/17202/Simple-FTP-demo-application-using-C-Net
What I would do is handle a double-click event in lstFiles which would invoke a function that sends a command to the FTP server to change to the directory indicated by the clicked text.
I'm not familiar enough with the .Net FTP-related classes to know how to send the change directory command, so I would start by looking at the documentation for FtpWebRequest.
http://msdn.microsoft.com/en-us/library/System.Net.FtpWebRequest%28v=vs.110%29.aspx

IE8 on some pages the download file does not work

I am developing an application that allows the user to download an excel file with regular content(not bigger then a few Mb).
On IE9 the file gets downloaded perfectly, but on IE8 some of the pages that allow the download does not work.
A new page is opens and closed right away without showing the download bar.
The cache control header is set to private.
I have disabled all of my IE8 add ones.
I have matched the response from the server for both the page that does allow the file saving and the one that does not work and they match exactly ( apart from the path )
I dont know why on some cases the file gets download perfectly and on others it dont.
Here is the server side code that I use to download the file:
protected void GetExportedFile()
{
string filename = Form("filename");
if (string.IsNullOrEmpty(filename))
{
Logger.Instance.Write("GetExportedFile is missing the parameter filename");
Response.Redirect("ErrorPage.aspx");
}
string filePath = Context.Server.MapPath("****/****/" + filename);
Response.ClearHeaders();
Response.ClearContent();
SetContentType(ContentType.Excel);
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", filename));
Response.WriteFile(filePath);
Response.Flush();
try
{
File.Delete(filePath);
}
catch (Exception ex)
{
Logger.Instance.Write(
"GetExportedFile failed to delete the file '" + filePath +
"', Error: " + ex.ToString(), "Error");
}
try
{
Response.End();
}
catch (ThreadAbortException ex)
{
//Don't add anything here.
//because if you write here in Response.Write,
//that text also will be added to your text file.
}
}
I have to mention although I dont think it is relevant that prior to the downloads that don't work on IE8 I am making some ajax calls to get notify if the excel generation has finished, while on the page that does work I dont do this procedure.
I will also like to add that my application resides behind an application firewall (F5) and when deactivated makes all of the downloads work on IE8, the issue is I am not not seeing any changes in the response.
thanks
If anyone see this post, I have found the reason for the problem.
IE8 has a security policy that will not allow a file download to be invoked directly from a script request.
Since I have invoked a series of ajax calls to the server querying the file creation state and when the file was ready issued a download call, IE has canceled it.
To override IE8 policy, when the file creation has finished I have poped the client a window with a link to the file , when that link was clicked the file got downloaded successfully.
I hope it helps someone one day...

Creating a hyperlink to a physical path on the local PC, to files not part of the web site

I have some files in a folder on the harddrive, like C:\ExtraContent\ that has some PDF files. This folder is not part of the website. I was able to successfully upload a PDF to this folder using the default ASP.NET FileUploader, no problem.
What I would like to do is, create a hyperlink that links to a PDF in that folder C:\ExtraContent\somePDF.pdf
I am able to get close using a Button with the following code:
protected void Button1_Click(object sender, EventArgs e)
{
WebClient client = new WebClient();
Byte[] buffer = client.DownloadData("C:\ExtraContent\somePDF.pdf");
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", buffer.Length.ToString());
Response.BinaryWrite(buffer);
}
The above works in terms of opening the file. But I can't get this to work with an ASP.NET HyperLink.
The reason I want to use a HyperLink is so that the user can choose to right-click and Save As, to download a copy. If HyperLink controls can only link to relative paths, what can I do to get my desired result?
Note: making the files I'm trying to access part of the site is not practical for us.
Basically allowing access to the folder the way you describe is a real security risk (because it requires hacking at the permissions), isn't trivial and in general should be avoided. The way that you achieve your desired behaviour is something along these lines.
Firstly create a blank aspx or ashx page.
Secondly, either in the Page_Load or ProcessRequest you want to use code along the following lines
string filePath = "c:\\Documents\\Stuff\\";
string fileName = "myPath.pdf";
byte[] bytes = System.IO.File.ReadAllBytes(filePath + fileName);
context.Response.Clear();
context.Response.ContentType = "application/pdf";
context.Response.Cache.SetCacheability(HttpCacheability.Private);
context.Response.Expires = -1;
context.Response.Buffer = true;
context.Response.AddHeader("Content-Disposition", string.Format("{0};FileName=\"{1}\"", "attachment", fileName));
context.Response.BinaryWrite(bytes);
context.Response.End();
I haven't tested this and taken it from my head so it might need some tweeks but the above code should get you on the right track to cause the persons browser to begin downloading the file you provide.
EDIT: I just realized (after rereading your question) your problem was slightly different to what I thought, to get your issue resolved simply make the hyperlink button you are using link to a page that can process the request as described above. IE: An ashx or aspx page
You need to create a hyperlink to a page that acts as a 'proxy' so that the page will return a response that contains the file stream.
You cannot create a link to a file that is not prt of your site.

Any possible way to programmatically save to another folder other than the designated downloads folder?

I'm developing a ASP.NET Web application in which a table is converted to an excel spreadsheet. I would like to give the option to the user to save somewhere else than the downloads section. I realize that is a good likelihood that this is prohibited, but maybe there is some sort of class/mechanism facilitated by ASP.net framework.
Here is my current code:
protected void saveDataButton_Click(Object sender, EventArgs e)
{
SaveFileDialog browser = new SaveFileDialog();
string fileName;
if (browser.ShowDialog() == DialogResult.OK)
{
fileName = browser.FileName;
}
else
return;
DataTable table = (DataTable)Session["tableData"];
HttpContext context = HttpContext.Current;
context.Response.Clear();
context.Response.ContentType = "text/csv";
context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName + ".csv");
foreach (DataColumn column in table.Columns)
{
context.Response.Write(column.ColumnName + ";");
}
context.Response.Write(Environment.NewLine);
foreach (DataRow row in table.Rows)
{
for (int i = 0; i < row.ItemArray.Length; i++)
{
context.Response.Write(row[i].ToString().Replace(";", string.Empty) + ";");
}
context.Response.Write(Environment.NewLine);
}
context.Response.End();
}
I know the way I'm using fileName is wrong in this context, as fileName is actually storing file path + file name in my code. Any way to specify a file path?
The only other solution I can think of is if I created the some sort of file on the page and had them right click + save as. Is this a bad alternative? Are there others?
No. The web application doesn't know anything about the local file system. (Indeed, aside from the content-disposition header, the HTTP protocol doesn't even really know what a "file" is.)
What you're doing (aside from having the full path in the content-disposition header) is correct. The standard way to send a file to a web client is to set that header and write the file content to the output. What happens on the client-side is entirely up to the web browser. If the user's web browser is set to automatically save downloads to a specific folder without prompting then you can't change that from the server.
no, where the file is saved on the user's computer is dictated by the web browser, it has nothing to do with the web server. think about it, you don't know what operating system a site visitor is running, let alone some arbitrary path you specify on the server.

Categories