Saving temporary files in web applications






3.59/5 (5 votes)
As you know, the main difference between web and desktop applications is one is stateless and the other is not. What if you need to save files in a temporary place before inserting them into a database? This article describes the problem and has a solution.
Introduction
As you know, the main difference between web and desktop applications is web applications are stateless but desktop applications are not. A web server does not keep all the information of each request, just some information like the session where you can store some data like login of user etc. ASP.NET uses a workaround for this - hidden fields. All important information is serialized after each request and saved in hidden fields. So during the next request, the web server can restore the state of the page controls.
Assume that we need to create a page where the user can add a folder and all the documents that are directly placed in the folder. The interface of such a form will look as in the figure below:
Using this form, the user can add a new folder and upload as many documents as he/she wants - folders and documents we want to save in the database. Obviously, there will be a foreign key between two tables in the database, and to add a document in the Documents table, we need to know the primary key of the folder. The problem is we cannot know the ID of the folder before inserting the record in the Folders table. So how will we save the documents?
Solution
Actually, you can simplify this form and not allow the user to add documents on the "Add Folder" form, but allow it on the "Edit Folder" form where the folder ID will be determined. But this approach is a little bit confusing. At first, we need to provide help information to the user about how to add documents and why he/she cannot do it on the "Add" page. Secondly, the user has to do the move actions to achieve the target.
To attain the ability to add documents on the "Add" page, we need to think about how to temporarily save documents on the server. For storage, I'm going to use a folder and will call it "Temp". In this folder, for each temporary file, I'm going to create a folder. The name of the folder will contain the session name and date time information. The session name will guarantee that each user will save the files in a unique directory, and I'm going to use the date time value to determinate when the files from the Temp folder can be removed. All of this functionality has been implemented in the TempUpload
class. To save a temporary file, I use the following code:
TempUpload tempUpload = new TempUpload(fileDocument);
String documentPath = tempUpload.SaveFile();
You need to pass the FileUpload
control to the TempUpload
constructor and then call the SaveFile
method which returns the path of temporarily saved file. Please note that the TempUpload
class does all the work from saving files to clearing the Temp folder of old files.
Now, file has been saved, and the request has finished. One more thing we need to do - add information about the uploaded file in the ViewState, so we can collect information about all the uploaded documents. To accomplish this, I will use a generic collection List<>
, and the items of this collection will be an object of the DocumentFile
class:
[Serializable]
public class DocumentFile
{
private String _id;
private String _documentTitle;
private String _documentFilePath;
public String ID
{
get { return this._id; }
set { this._id = value; }
}
public String DocumentTitle
{
get { return this._documentTitle; }
set { this._documentTitle = value; }
}
public String DocumentFilePath
{
get { return this._documentFilePath; }
set { this._documentFilePath = value; }
}
public DocumentFile(String id, String documentTitle,
String documentFilePath)
{
this._id = id;
this._documentTitle = documentTitle;
this._documentFilePath = documentFilePath;
}
}
First of all, objects of this class have to be serializable because we are going to save them in the ViewState. That's why I added the [Serializable]
attribute to the DocumentFile
class. After dropping this class in the App_Code folder, I can add the _documents
property to the "Add folder" page:
private List<DocumentFile> _documents
{
get
{
if (ViewState["Documents"] == null)
ViewState["Documents"] = new List<DocumentFile>();
return (List<DocumentFile>)ViewState["Documents"];
}
set
{
ViewState["Documents"] = value;
}
}
Now, let's add some code to the Click
event handler of the LinkButton
"Add Document":
protected void lnkAddDocument_Click(object sender, EventArgs e)
{
if (IsValid)
{
TempUpload tempUpload = new TempUpload(fileDocument);
String documentPath = tempUpload.SaveFile();
_documents.Add(new DocumentFile(
Guid.NewGuid().ToString(),
txtDocumentTitle.Text,
documentPath));
...
}
}
There is the TempUpload
object mentioned above. After the file is saved, I add its data to the _documents
collection.
In the DataBind
method, we can use the _documents
collection as the data source for the GridView
to show a list of uploaded documents:
public override void DataBind()
{
base.DataBind();
grdDocuments.DataSource = _documents;
grdDocuments.DataBind();
}
The last thing is saving the folder and all the uploaded folders. After inserting a new folder in the database, get the folder ID, which will be added to the Documents table to enable the foreign key. Because all documents are saved in a temporary folder, we need to move all the files to permanent storage. It could be another folder on the server, or you can save files in the database directly.
Download the latest sources of the example web application from here.