Forward files from internal server to HTTP request - c#

Maybe the title I have does not reflect my Question 100% but I will try to make it clearer. That is how our system is right now.
We have an Webserver that is public on the internet and the Webserver that has access to a Fileserver. We would like without having files on the Webserver the client to be able to download files from the Fileserver. Is there any technology available for these kind of requests?
We are using ASP. NET WebForms.
Thanks in advance.

I don't know of any Framework that would do this but I implemented something similar. In our case we have a list of the files that users should be able to download in a database but you could simply use System.IO.Directory to query for the available files in a certain folder yourself. It's also required that the application runs in an application pool that has an identity (User) that is allowed to access the fileshare.
The actual download is implemented as an ASP.Net WebHandler (.ashx-File). When the user hits that Handler I basically do something like this in the ProcessRequest method:
string fileName = "\\\\myServer\\folder\\file.pdf";
byte[] fileContent = System.IO.File.ReadAllBytes(fileName);
context.Response.Clear();
context.Response.ClearHeaders();
context.Response.ClearContent();
context.Response.ContentType = "application/pdf";
context.Response.AddHeader("Content-Disposition", "attachment;filename=" + System.IO.Path.GetFileName(fileName));
context.Response.AddHeader("Content-Length", fileContent.Length.ToString());
context.Response.BinaryWrite(fileContent);
Of course if you are dealing with bigger files you might want to not load the entire file into memory but rather read in chunks and make multiple calls to BinaryWrite. You also should set the ContentType to a MIME-Type that fits your file type so it gets handled correctly by the clients browser.

Related

asp.net hide download

I am making an application to edit mp3 files. After the editing is finished I want to present a link to download the file. I am just concerned that the file location, if known, can be abused for illegal files. What do I need to do so that, instead of presenting a link to a file on the server, I can store it in memory (which I already have using taglib) and then stream the download without storing it on the server.
You need to use an HTTP Handler to write the file to the user while masking the true location of the file on the server. This will enable you to enforce whatever rules you may have regarding the downloading of the file, such as a one time download.
See: How to create an HTTP Handler
The code inside the handler will need to be unique to your needs, but something along the following lines should help:
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "Application/mp3";
context.Response.AppendHeader("Content-Disposition", "attachment; filename=mysong.mp3");
context.Response.TransmitFile(Server.MapPath("~/Files/song.mp3"));
}
You could use a Stream in case you don't want to save an actual file anywhere, but this should get you started.

Serving an exe to Firefox from an aspx. Firefox downloads it as "Content". Incorrect filename and no extension

I'm trying to server an exe to Firefox from an aspx page. The aspx page handles the headers and the page is launched by our Flex GUI. Flex correctly launches the link for all browsers (including Firefox) so I'm certain that's not the issue.
The problem I'm having is when I try to download the file from within Firefox, FF downloads the file fine but it names it "Content". It has no extension and the file name is incorrect. All the other browsers download it with the file name I specified in the aspx page and they all have the .exe extension. I should note that if I rename the "Content" file to "Content.exe" it runs correctly.
Below is the code I'm using in my aspx page -
protected void Page_Load(object sender, EventArgs e) {
string fileName = Request.QueryString["file"];
System.IO.FileInfo fileInfo = new System.IO.FileInfo(Server.MapPath(fileName));
Response.Clear();
if ( fileName.EndsWith(".exe") ) {
Response.ContentType = "application/exe";
}
else {
Response.ContentType = "application/octet-stream";
}
Response.AddHeader("Content-Disposition", "attachment; filename=" + fileInfo.Name);
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.WriteFile(fileInfo.FullName);
Response.Flush();
}
Any ideas and/or suggestions on why this isn't working correctly in Firefox?
I just ran the exact code you have mentioned, without the Flex GUI part, in a simple asp.net website, and it works fine on my Firefox, I am getting file name with extension.
I am using Firefox version 3.6.16.
Here are few things you can try:
Try running the same code without Flex GUI part
If it still doesn't work, check your firefox version
As suggested by Jon, use Fiddler and observe if something wrong in the response headers
One more point, may be this is just for test purpose, as allowing to download files this way can be a security threat, as even if the url is being called from Flex GUI, people can monitor traffic using fiddler or wireshark, and then exploit it to download any file they want to. For example they can download web.config and see connection string, or they can download the code.
You should restrict user to download file from one location only and only few allowed extensions.
There's no need for you to add the content-length yourself, as Response.WriteFile will do that if appropriate. The resultant duplicate headers is incorrect.
I'd also avoid flushing at the end, firstly flushing is only useful if it happens part-way through a long download; done only at the end you get the disadvantages of chunked encoding, without any of the advantages. This may also interfere with the content-length header you are sending.
Finally, there is no registered content type "application/exe", "application/octet-stream" should be used for executables. Maybe since Firefox is seeing it as "wrong" for .exe files, it's not using that extension.
If none of the above solves it, I'd recommend updating your question with the headers sent from the browser as seen through Fiddler or similar tools, as that may help someone find the answer (or you yourself for that matter).

Display PDF - Application Page SharePoint

I am working on a Custom WebPart, for which I need an application page to render a PDF file.
I am currently using following link http://support.microsoft.com/kb/306654
It works fine in ASP.NET, but gives a blank page in SharePoint.
Here's the code:
(PDF file is in same directory)
Response.ClearContent();
Response.ClearHeaders();
//Set the appropriate ContentType.
Response.ContentType = "Application/pdf";
//Get the physical path to the file.
string FilePath = MapPath("Test.pdf");
//Write the file directly to the HTTP content output stream.
Response.WriteFile(FilePath);
Response.Flush();
Response.End();
Working on it for last few hrs, making me crazy...any ideas?
A few ideas:
If the file is in the SharePoint directories, why not just redirect to a URL for it?
If you use Fiddler (or Firebug) to look at the HTTP traffic -- do you see the content-type change? What is the content (is it a PDF?)
The main differences between SharePoint and ASP.NET (assuming that you are getting to the file correctly) is that the page life-cycle is slightly different and the security model. You might want to look at how Reponse.End() works to make sure it isn't different in SharePoint. You can run SharePoint in verbose logging and then use .NET Reflector on the SharePoint dlls (with the logs as a guide) to see if there's some weird way of handling this. The SharePoint dlls have pretty liberal log calls. More info here: http://www.andrewconnell.com/blog/archive/2008/06/11/SharePoint-Debugging-and-Logging-Tips-and-Tricks.aspx
Have you considered rasterizing the PDF and just showing it inline in the page? This is what we do in a project my company is working on to view PDF and other documents in SharePoint (Vizit). You still have to solve your problem of reading the file, but instead of responding with the PDF, you respond with a PNG and request inside of an <img> tag.

Download file from webservice - in ASP.NET site

I want to push a file to the browser from a website using a webservice. I'm currently reading the file into a base64 byte array, and returning that from the webservice. This webservice is called from a website, and i'm stuck on how to push this as the original file to the browser. Ideally I would like to read the byte array into a memory stream, and then just write it to the Response stream if possible so the end user just downloads the file.
First, rather than send a base64 byte array, have your web service simply return a byte array for your file. Response.OutputStream.Write() will automatically base64 encode your bytes, so you might as well have them un-encoded in your memory stream.
Second, you'll need more than just the bytes. You'll need meta-data associated with the file. For the snippet below, I've placed all of that metadata into a separate class (local instance named "file"). Then, just use this snippet, once you have the data you need:
Response.Clear();
Response.ClearHeaders();
Response.ContentType = file.ContentType;
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + file.FileName + "\"");
Response.AddHeader("Content-Length", file.FileSize.ToString());
Response.OutputStream.Write(file.Bytes, 0, file.Bytes.Length);
Response.Flush();
Response.End();
It's possible, you'll need to make sure you explicitly set the ContentType of the HttpResponse, for example:
Response.ContentType = "image/jpeg";
Response.OutputStream.Write(buffer, 0, buffer.Length);
If you want to control the file name, you'll have to add a Content-Disposition header. Google can help you find the right way to sort that out.
Its usually a bad idea to embed a file in a web service. You just add overhead and complexity with no real benefit.
Instead you should provide a IHttpHandler to handle the file upload. Most web servers also provide helper API's to simplify this, e.g. in ASP.NET you can access the uploaded file with:
HttpContext.Request.Files[0]
There are plenty of javascript file upload scripts that simplify this on the client:
http://www.phpletter.com/Demo/AjaxFileUpload-Demo/
It really depends on the interface to your webservice. Ie SOAP, REST, ASPX.
One thing you can try is to change the content-type in your Response to "Application/octet-stream". Or something similar to tell the receiver the MIME type.
If your using WCF rest you can use Stream as a return type on the web service.

Response.WriteFile with a URL possible?

I would like to be able to do this:
Response.WriteFile ("http://domain/filepath/file.mpg")
But, I get this error:
Invalid path for MapPath 'http://domain/filepath/file.mpg'
A virtual path is expected.
The WriteFile method does not appear to work with URLs. Is there any other way I can write the contents of a URL to my page?
Thanks.
If you need the code to work in that manner, then you will have to dynamically download it onto your server first:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://domain/filepath/file.mpg");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream file = response.GetResponseStream();
From that point, you have the contents of the file as a stream, and you will have to read/write the bytes out to the response.
I will mention however, that this is not necessarily optimal--you will be killing your bandwidth, because every file will be using far more resources than necessary.
If possible, move the file to your server, or rethink exactly what you are trying to do.
A possible solution would be to simply use:
Response.Redirect("http://domain/filepath/file.mpg")
But then, I am not sure if that is what you are really trying to do or not.
Basically you have a couple of choices. You can either download the file to your server and serve it with Response.WriteFile or you could redirect to the actual location. If the file is already on your server you just have to provide a file system path to Response.WriteFile instead of the url, or use a virtual url, by removing http://domain.

Categories

Resources