Problem:
Managing files web applications should be quick and easy and most importantly, consistent. The traditional way to store files is on the file system or within a RDBMS (SQL SERVER, Oracle, MySql) or on SharePoint. However what if you were developing several applications that shared a million files and each was 5MB. Which solution would you choose? This is commonly the case for large content driven sites (Music Stores, video sharing sites, content management systems, etc).
Solution:
In providing a solution I would implement a SOA based File Service, and this article will guide you to making your own File Service. The reasons that I believe a File Service works are:
- Single point of storage for data
- Can be used by multiple applications
- Single source for security
- Easy to de-duplicate files
- Clear separation between binary data and metadata
- Efficient file system usage ensuring that director retrieval is fast
- Efficient IO usage using multiple disks (per share)
Data Structure:
Firstly we need to create a table to store our file information. Most columns on the table shown in Figure 1 are self explanatory and for possible enhancements see the "Future Enhancements" section below.

Figure 1
Figure 1
Solution Structure:
- Create a new Solution in Visual Studio 2008, targeting the .NET Framework 3.5
- Create a new Class Library called "FileServiceCore"
- Add a new class called "FileHandlerFactory.cs"
- Add a new class called "FileHandlerLinq.cs"
- Add a new class called "FileDistributor.cs"
- Add a new LINQ to SQL Classes called "FileService.dbml"
- Using the Server Explorer create a new connection to the database that contains the "Files" table described above. You should be able to drag and drop the table onto the designer.
- Create a new Website called "FileService"
- Add a project reference to the FileServiceCore
- In the website root add a new generic handler called "ImageHandler.ashx"
- In the website root add a new generic handler called "DownloadHandler.ashx"
- Create a new website called "SampleWebsite"
- Add a project reference to the FileServiceCore
Your solution should now look like figure 2 below.
Figure 2
Logic:
Now that you have created your Data Structure and Visual Studio solution we will need to add the application logic to each of the classes (e.g. FileHandlerFactory.cs).
FileDistributor.cs
The FileDistributor class is responsible for distributing files to the file system. It contains a single static method that calculates a network file path for a FileId.
namespace FileServiceCore
![]()
FileHandlerLinq.cs
The FileHandlerLinq class is a static class that each calling application can use to Insert/Select files from the Files table. For the purpose of this example update and deletes have been omitted.
FileHandlerFactory.cs
The FileHandlerFactory is a simple factory class that determines if the browser should handle the file or if the file should be downloaded by the client as an attachment. In this example the factory is simple and should be customized for your own needs.
using System;
using System.Web;
namespace FileServiceCore
DownloadHandler.ashx and ImageHandler.ashx
DownloadHandler.ashx and ImageHandler.ashx
The Generic ImageHander and DownloadHandlers are almost identical and their sole purpose is to parse the Uri for the FileId token. Once the FileId token is collected the generic handler calls for a file handler from the File Handler Factory.
<%@ WebHandler Language="C#" Class="DownloadHandler" %>
using System;
using System.Web;
public class DownloadHandler : IHttpHandler
Default.aspx
Default.aspx
The below sample .aspx page shows a common usage to add data to the file service.
![]()
Code Behind: --------------------------------------------------------using System;
using System.Globalization;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void UploadFileButton_Click(object sender, EventArgs e)
{
if (UploadFileControl.HasFile)
{
// get the acutal file name
string fileName = UploadFileControl.PostedFile.FileName;
fileName = fileName.Substring(fileName.LastIndexOf(@"\", StringComparison.OrdinalIgnoreCase) + 1);
// insert our file and redirect back to this page with the fileId appended to the querystring
FileServiceCore.File fileEntity = FileServiceCore.FileHandlerLinq.Insert(
fileName,
UploadFileControl.PostedFile.ContentType,
UploadFileControl.PostedFile.InputStream);
// redirect back to our page
Response.Redirect(string.Format(CultureInfo.InvariantCulture, "default.aspx?FileId={0}", fileEntity.FileId));
}
}
}
![]()
Future Enhancements:
The following list highlights some of the possible enhancements that can be made to the service, depending on your needs:
- Public/Private flags for files
- Cache headers for the ImageHandler
- Resizing/cropping/effects for the ImageHandler
- Store statistics for file usage (last accessed, times accessed, etc)
- Demotion of non used files to another storage medium (tape, DVD, etc)
- File locking, to ensure files aren't accidentally deleted.
Assumptions:
- There is an available NAS/SAN with enough storage capacity for your needs
- The IIS account running the File Service has appropriate permissions to read/write to the NAS/SAN
本文转载 kane-nina
http://www.kanebarton.com/Samples/FileService/Default.aspx