Serving Files from another domain

By in
No comments

I’ve recently needed to develop a method to allow users to access files that are on a restricted domain. This domain is on an internal server that has no external access. However, it serves documents and files to a webserver that is accessible externally. So the webserver has access to the files, meaning they can upload files to the webserver, which will then save them to the internal server… But the reverse is not true. So we needed a way to “copy” files from the internal server to the end user.

My solution was to use an ASHX handler that will process the users request and retrieve the requested document, streaming it to the user through the response output stream. this is relatively new territory for me, but nothing ventured nothing gained!

The file is located by retrieving parameters passed through the querystring for the date, folder, and filename. This is mapped to a location on the webserver. I begin by validating the input. This probably isn’t the best method for validating input but it should do the job until I have more time to optimize it. Please feel free to suggest anything I’ve overlooked!

	// retrieve qstring fields, ensure all are present
	string date = context.Request.QueryString["date"];
	string folder = context.Request.QueryString["key"];
	string file = context.Request.QueryString["file"];
	if (string.IsNullOrEmpty(date) || string.IsNullOrEmpty(folder) || string.IsNullOrEmpty(file))
	{
		context.Response.Write("File not found");
		context.Response.End();
	}
		
	// prevent directory attacks
	if (date.Contains("../") || folder.Contains("../") || file.Contains("../"))
	{
		context.Response.Write("File not found");
		context.Response.End();
	}

Next I built a webrequest to retrieve the file by formatting a url string and retrieveing the response (which is the pdf file itself);

        // build request stream
	string url = string.Format("http://INTERNALIP/{0}/{1}/{2}", date, folder, file);
	HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
	HttpWebResponse resp = null;
	try
	{
		 resp = (HttpWebResponse)req.GetResponse();
	}
	catch (Exception ex)
	{
		context.Response.Write("File not found");
		context.Response.End();
	}

	Stream rStream = resp.GetResponseStream();

Finally, I initialize the response, filling it with the binary data from the pdf file, and writing to the stream as a pdf file attachment.

	// initialize response
	context.Response.Clear();
	context.Response.ContentType = "application/pdf";
	context.Response.AddHeader("Content-disposition", string.Format("attachment; filename={0}", file));
		
	// create buffer to input data
	int buffersize = 1024 * 16;
	byte[] buffer = new byte[buffersize];
	int count = rStream.Read(buffer, 0, buffersize);

	while (count > 0)
	{
		// write content to response
		context.Response.OutputStream.Write(buffer, 0, count);
		count = rStream.Read(buffer, 0, buffersize);
	}

	context.Response.End();

Now all that is necessary is to build the url to the handler with the appropriate fields in the querystring, like http://externalsite.com/pdf.ashx?date=20080828&folder=stuff&file=thefile.pdf and sure enough the handler does all the work! Not too shabby for my first real ashx application!

As always your comments are welcome and appreciated

The following two tabs change content below.

selaromdotnet

Senior Developer at iD Tech
Josh loves all things Microsoft and Windows, and develops solutions for Web, Desktop and Mobile using the .NET Framework, Azure, UWP and everything else in the Microsoft Stack. His other passion is music, and in his spare time Josh spins and produces electronic music under the name DJ SelArom. His other passion is music, and in his spare time Josh spins and produces electronic music under the name DJ SelArom.