This blog is based on my recent requirement where I had to save some image files from one website to another website. Lets see the requirement and the solution for the requirement.
Requirement
The requirement is as follows. The user will select a file which needs to be uploaded using a website (UploadFilesWebsite) and these selected files will be saved in another website (SaveFilesWebsite). Cross website posting of data. We all know it’ very easy to save files within the same site by making use of a file upload control and calling its SaveAs method. E.g. is pasted below.
fileUploadCntl.SaveAs(System.IO.Path.Combine(Server.MapPath("."), fileUploadCntl.FileName)) |
But in my case it was different, the file needs to be saved in a different website from the one from where file upload is done.
Solution
The problem was solved by making use of HttpWebRequest and HttpWebResponse object. Below is steps which are needed to solve this problem.
- First create an ASPX file which will be capable of receiving any type of file stream and saving this stream to the required folder. This file should be created/placed in the website where you want to save the files, in my case it is “SaveFiles” website.
- Create a HttpWebRequest object and pump the file content to the RequestStream of the HttpWebRequest object.
- Get the response using the GetResponse method of the HttpWebRequest object. GetResponse will return a HttpWebResponse object.
- Get the response stream from the HttpWebResponse object by executing the GetResponseStream method.
These are the steps which you need to follow to post file contents from one website to another. Lets see each one of these one by one.
Create an aspx file capable of saving request stream.
The first step is to create an aspx file which will be capable of saving a request stream. This file should be created and saved in the web site where you plan to save your file. This file will receive requests from other website for saving files in the website. So we will create this file in “SaveFiles” website and we will name it as SaveFile.asxp. After creating and saving the file go to the HTML source view of the file. It will look something like this.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SaveFile.aspx.cs" Inherits="SaveFile" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> |
Remove the HTML source from the file leaving only the Page attribute. The page should look something like this.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SaveFile.aspx.cs" Inherits="SaveFile" %> |
Now lets go to the codebehind and do some coding to save the request stream. The codebehind (SaveFile.aspx.cs) file of SaveFile looks something like this.
using System; public partial class SaveFile : System.Web.UI.Page |
From the above code one can see we are first retrieving the filename from Request object’ Headers property. We will shortly see how to send info in headers of a request. After getting the filename we are opening a file stream to flush the content to the hard disk. Once the file stream is successfully created, next, we are creating a stream by getting the InputStream of the Request object. The InputStream property of the Request object will hold the content which needs to be saved. In the next line we are reading the stream content to a byte array and finally passing the byte array to the FileStream object and writing/saving to a file. Once the file is successfully saved we are writing the status to the Response after clearing the Response. Also if there is any exception thrown while the file is saved the same is written to the Response.
So that’ about the page which will save the content in the desired filename. So now we will move to our next steps like creating the HttpWebRequest object and passing the file content to the SaveFile.aspx file to save it in the website.
Create an aspx page to upload the images.
The file which we will be creating will have the capability to upload files from the user’ hard disk and will send these file contents to the SaveFile.aspx page. The UploadFile.aspx will be created in a separate website/virtual directory called “UploadFiles” website. This aspx page will have a FileUpload control and a save button. So here is the HTML source of UploadFile.aspx.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="FileUpload.aspx.cs" Inherits="FileUpload" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> |
From the HTML you can see that we have an FileUpload control and a save button with an OnClick event handler. So that’ our simple UploadFile page. Now lets see the real action i.e. the place where the code to upload files and sending the content of these files to the SaveFile.aspx in “SaveFiles” website happen. So here is the click event of the save button where all the action takes place.
protected void btnSave_Click(object sender, EventArgs e) |
In the above code first I am creating a WebRequest object by passing the URL of the page which will handle the saving mechanism. Once the WebRequest object is created next I am assigning the Method as POST. This is a very important step. If you don’t assign the method property it will default to “GET”. If you use “GET” as the method to send data then you will receive System.Net.ProtocolViolationException with the following message.
"Cannot send a content-body with this verb-type." |
Once the method is set to “POST” we are setting the KeepAlive property to false. KeepAlive property will be responsible for maintaining a live connection. The next line we are setting the ContentType of the request. The content type can be easily retrieved by calling the ContentType property from PostedFile property of the FileUpload Control. Next line we are creating a WebHeaderCollection object to pass additional information in the headers of the request. You can see we are passing the file name as one of the header value. These header details are read in SaveFile.aspx. So if you want send some extra information you can do that using WebHeaderCollection. In the next few lines we are retrieving the request stream using the GetRequestStream method and then writing the contents of the selected file to request stream using the Write method of the Stream object. To pump the content of the chosen file we are making use of the FileBytes property of the FileUpload control. One can note that we are making use of the “using” statement quite a lot. To know more about the usefulness of the “using” statement you can refer my blog on using statement here.
Once the FileUpload contents are pumped to the request stream of the HttpRequest object in the next line I am creating the HttpWebResponse using the GetResponse method of the HttpWebRequest object. So what GetResponse does is that it sends a request to the Url (savefile.aspx) specified while creating the HttpWebRequest object. When the HttpWebRequest object sends request to the url its similar to the way we access url through the browser. So the whole life cycle of the page executes and response is saved in the form of HttpWebResponse object. After getting the HttpWebResponse object we are reading what output was returned by the page using the StreamReader object’ ReadToEnd method. You can retrieve the StreamReader object by calling the GetResponseStream method of the WebRequest object. The response which I am getting is directly assigned to the Text property of a label control. What we get in the ResponseStream object is what we have written to the response using the Write method of the Response property in the SaveImage.aspx page. So if the image is successfully saved we get “File Successfully saved” as the response else we get error as the response.
That’ it, we are done. With this technique we can save files or contents from one website to another site i.e. cross website posting of data. This technique is very simple but can be very dangerous. You should make sure that you implement some sort of authentication so that hackers can be evaded from saving some malicious files.
Try to know more.
Sandeep