I am trying to implement force download file dialog in my ASP.NET C# application. The files I'd like to force download are media files not locally available available on the web server but are being served from a different location.
I am getting an error 'http://remote-site-to-webserver/somefile.asf' is not a valid virtual path.
I have searched the web for solutions but all examples point to relative path on the server using Server.MapPath
In the example below I created a webhandler.ashx page and send the download request to this page.
<%# WebHandler Language="C#" Class="DownloadHandler" %>
using System;
using System.Web;
public class DownloadHandler : IHttpHandler {
public void ProcessRequest(HttpContext context) {
var fileName = "http://remote-site-to-webserver/somefile.asf";
var r = context.Response;
r.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
r.WriteFile(context.Server.MapPath(fileName));
}
public bool IsReusable { get { return false; } }
}
The Content-Disposition header looks wrong to me. I think it should be:
r.AddHeader("Content-Disposition",
"attachment; filename=DefaultNewFilename.ext");
the filename is the default name given to the downloaded file... Or in otherwords it's what is shown in the browsers save dialog.
You may also want:
r.AddHeader("Content-Type", "application/octetstream");
I'm not sure that's required.... But I've always included it for video files and so on.
In order for the download to start from a different server, you need to send a redirect answer to the client (Response.Redirect(mediaURL)).
As a consequence, you cannot force the download dialog from your web server because the browser will send a separate request to the other server. This must be solved on the server where the media is served from.
The only alternative is that you act as an intermediate, i.e. you download the media file to your server and send it as the response to the client. This shouldn't be too difficult if it's a small file that easily fits into memory. However, if it's a large file it might involve some tricky coding so you can receive and send it piecewise.
Server.MapPath()
is not used for remote http files. it is just a tool for converting virtual addresses to physical addresses, i.e. you can retrieve "C:\inetpub\wwwroot\MyWebSite\Files\blah.txt" by giving "~/Files/blah.txt" to Server.MapPath method.
if you are interested in downloading a file from another web server you will have to use HttpWebRequest class.
this is a sample code:
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create("http://remote-site-to-webserver/somefile.asf");
httpRequest.Credentials = CredentialCache.DefaultCredentials; //or a NetworkCredential if needed
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream dataStream = httpResponse.GetResponseStream();
now you can output the dataStream into your response.
Related
I am trying to store data from a xml file located in this link : Link to xml file
The xml file basically contains questions as well as options relating to English grammar. The main reason for saving these file is that I can parse these information later
From the browser (Chrome or IE), the xml file is loaded normally yet saving it programmatically did not work. The issue is that the data retrieved from that URL appeared to be something else.
This is my code for getting data from the URL
using (WebClient client = new WebClient())
{
client.Encoding = Encoding.UTF8;
// the data retrieved is something meaning : "Link does not exist"
string data = client.DownloadString("http://farm04.gox.vn/edu/IOE_Exam/IOE/l5/v1/g1/exam1.xml?v=");
}
The above approach gives nothing but a string which indicates there isnt such a link (though I still think the server itself sends it rather than a 404 error).
My second attempt is using WebRequest and WebResponse but no luck. I have read that WebClient is a wrapper class for the latter method so both give the same result
WebRequest request = WebRequest.Create(Url);
WebResponse response = request.GetResponse();
using (Stream stream = response.GetResponseStream())
{
return new StreamReader(stream).ReadToEnd();
}
I suppose the server has a mechanism to prevent client from downloading it. However Chrome would do the job successfully by loading the page then "Ctrl + S" (Save as ..) to save the xml file without any problems.
What the differences between browser and WebClient API ? Is there additional action which the browser implements ?
Any suggestion would be much appreciated.
I have a application, which logs you on to a website and then downloads some files from that website.
Although, I have been able to download all the type of files and save them properly except whose link redirects to another page.
for ex if in the source code of the web page , the link address is written as :-
"http://someurl.com/view.php", then this link redirects and the download immediately starts(when we click on the link in a web brwoser).
I have been able to download this file programmatically using HttpWebRequest
and then setting the AllowAutoRedirect = true.
The problem arises while saving, I need to have the extension of the downloaded file(whether it is a word document, pdf file or some other file)
How should I check that?
Some of the code which I am using is :-
HttpWebRequest request = WebRequest.Create(UriObj) as HttpWebRequest;
request.Proxy = null;
request.CookieContainer = CC;
request.AllowAutoRedirect = true ;
request.ContentType = "application/x-www-form-urlencoded";
When you get a redirected response, the ResponseUri property will give you the URI of the resource that actually responded.
So if http://someurl.com/view.php redirected to http://example.com/foo.doc, then ResponseUri will contain http://example.com/foo.doc.
Understand that the "extension" might not be what you expect. For example, I've seen a URL like http://example.com/document.php return a PDF file. I've seen URLs with ".mp3" extension return image files, etc.
You can check the ContentType header, which is usually a more reliable indicator of the actual content of the response, but not a guarantee.
I'm pretty sure this isn't possible but I thought I'd ask...
I have a FileResult which returns a file, when it works there's no problem. When there's an error in the FileResult for some reason, I'd like to display an exception error message on the users screen, preferably in a popup.
Can I do an Ajax post which returns a file when successful and displays a message if not?
I think it is not possible cause in order to handle ajax post, you will have to write a javascript handler on the client side and javascript cannot do file IO on client side.
However, what you can do is, make an ajax request to check if file exists and can be downloaded. If, not, respond to that request negatively which will popup a dialog on client side. If successful, make a file download request.
Not specifically related to MVC but...
it can be done using XMLHttpRequest in conjunction with the new HTML5 File System API that allows you to deal with binary data (fetched from http response in your case) and save it to the local file system.
See example here: http://www.html5rocks.com/en/tutorials/file/xhr2/#toc-example-savingimages
Controller (MyApiController) Code:
public ActionResult DownloadFile(String FileUniqueName)
{
var rootPath = Server.MapPath("~/UploadedFiles");
var fileFullPath = System.IO.Path.Combine(rootPath,FileUniqueName);
byte[] fileBytes = System.IO.File.ReadAllBytes(fileFullPath);
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, "MyDownloadFile");
}
Jquery Code:
$(document).on("click"," a ", function(){ //on click of anchor tag
var funame=$(this).attr('uname'); /*anchor tag attribute "uname" contain file unique name*/
var url = "http://localhost:14211/MyApi/DownloadFile?FileUniqueName= " + funame;
window.open(url);
});
I am wondering if there is a c# or selenium solution to the following:
I am using selenium to download a file off a webserver.
unfortunately in IE9 there is no way to disable this popup screen.
is there a solution in c# for clicking on the SAVE button?
Client
WebClient client = new WebClient();
byte[] file = client.DownloadData("http://domain.com/default.aspx");
File.WriteAllBytes("helloworld.txt", file);
Server
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
using (MemoryStream memory = new MemoryStream())
using (StreamWriter writer = new StreamWriter(memory))
{
// The bytes written can be anything, does not have to be text
writer.WriteLine("hello, world");
writer.Flush();
Response.BinaryWrite(memory.ToArray());
}
Response.AddHeader("Content-Disposition", "Attachment; filename=helloworld.txt");
Response.AddHeader("Content-Type", "application/octet-stream");
Response.End();
}
}
As you can see with the above example, not only do I not know the physical location of the file, but there is no physical location! It is something I just wrote to memory and then wrote the raw bytes to the response, but WebClient.DownloadData() will still be able to download the bytes all the same. It doesn't care where the bytes come from. Hope this helps.
Additional Information:
Some further background information further explaining why the above works.
A browser's primary job is to send HTTP requests and handle the response. Fortunately, they handle a lot of the grunt work for us. Showing a simple web page involves sending an HTTP-GET to the server and receiving bytes back in the response body, decoding those bytes into text, and parsing that text to render an HTML web page. It knows to handle the response like that because it has a Content-Type header of Text/HTML. While this is what it does most of the time, browsers can also handle other MIME types, if the Content-Type is text/plain it will decode the bytes and just display them without trying to parse it. Text/XML will usually allow you to collapse and expand XML nodes, etc. Again this is all dependent on how the browser is programmed to handle that particle MIME type.
When you get a Save As dialog box in a browser, that is simply the browser's way of handling a response with a Content-Disposition: Attachment header. This header tells the browser not to try to render or display the content, but to download it as an attachment instead.
When you use the WebClient / HttpWebRequest classes, you are essentially writing your own miniature browser, however the implementation of how MIME types / HTTP headers are handled is entirely up to you. And this can allow you to save the bytes from a Content-Disposition response (or any response for that matter) without prompting with a Open or Save dialog box.
I am using the code,
string loadFile = HttpContext.Current.Request.Url.AbsoluteUri;
// this.Response.ClearContent();
// this.Response.ClearHeaders();
this.Response.AppendHeader("content-disposition", "attachment; filename " + filename);
this.Response.ContentType ="application/html";
this.Response.WriteFile("C:\\Users\\Desktop\\Jobspoint Website\\jobpoint3.0\\print.aspx");
this.Response.Flush();
this.Response.Close();
this.Response.End();
to download an aspx page in asp.net C#.. But its only showing the html tags and static values... How can I save the entire page without html tags and with the values that retrieved from the database?
Thanks...
Leema
Use WebClient for this. It will download your file.
If I have understood correctly, one option would be to actually make a request to the web server using WebClient for example. And then write the response to that request to the Response.OutputStream. This means that the server will actually make a second request to it self and then send the response to the second request back to the client.
This way you will have the web server actually process the request and return the resulting HTML back to you rather than just the raw aspx page.