Jeff Sandquist
Microsoft Corporation
May 24, 1999
I am often asked by Web developers how to get a file from their user's workstation to the file system of their Web server.
This month I will begin a two-part series in which we'll build an application that's based on Active Server Pages (ASP) and that uses the Microsoft® Posting Acceptor to upload files.
Your corporate Web site has a page listing all of your employees. For each employee in your organization, there is a photograph and a brief biography. Rather than having a Web developer tasked with updating this page, the Human Resources department will update the page using an internal Web page.
The Human Resources department will use the internal Web site to supply the employee's biographical information and upload the image file. They'll use the Posting Acceptor to upload the image file to the file system, and will use Active Data Objects (ADO) to insert the information into a Microsoft Access 97 database.
The external Web site will iterate through a table stored in an Access 97 database displaying the up-to-date employee information.
Microsoft Windows NT® 4.0 Option Pack installs ASP technologies, ADO, and other essential tools for your Web environment.
You will also need to install the Microsoft Posting Acceptor. Microsoft Posting Acceptor allows Microsoft Internet Information Server (IIS) to accept Web content posts (files) from Microsoft Web Publishing Wizard or other clients using the multi-form/posting method through an HTTP connection.
The Posting Acceptor uses an ISAPI extension DLL (CPSHOST.DLL), which implements the necessary parsing routines to break up multi-part data forms. Not sure which version of the Posting Acceptor is installed? Not even sure that it is installed at all? Complete the following steps:
Product | Installation Details | Version |
Microsoft Site Server 3.0 | Installs when the Content Management Component is selected in the Site Server 3.0 Setup | 7.0.794.7 |
Microsoft Visual Studio® 6.0 | PASetup.exe from the Deploy directory on Visual Studio 6.0 CD-ROM #2 | 7.0.794.7 |
Microsoft Visual Basic® 6.0 Enterprise Edition | PASETUP.exe from the Deploy directory on Visual Basic 6.0 Enterprise Edition CD-ROM #2 | 7.0.794.7 |
Microsoft Visual Interdev 6.0 | PASETUP.exe from the Deploy directory on the Visual InterDev 6.0 CD-ROM | 7.0.794.7 |
Microsoft Visual J++® 6.0 Professional Edition | PASETUP.exe from the Deploy directory on the Visual J++ 6.0 Professional Edition CD-ROM | 7.0.794.7 |
Windows NT 4.0 Option Pack | Installs when the Site Server Express Option is selected in the Windows NT Option Pack Setup | 6.1.27 |
Posting Acceptor 1.0 | Microsoft Posting Acceptor Web Download | 6.0.86.0 |
This sample will work with both Microsoft Internet Explorer (versions 3.02 or greater) and Netscape Navigator (versions 2.02 or greater). Posting Acceptor can also accept content posts from Internet Explorer 3.0 -- but instead of retrieving the results from a form, you'll have to use the ActiveX Upload control provided with the Microsoft Posting Acceptor Web Download .
For illustration purposes we'll use an Access 97 database. This works great for development and limited deployment scenarios. However, if you are building a high-demand, production-quality Web application, you'll get better results by using a client-server database, such as Microsoft SQL Server 7.0 .
In this example, we are storing the photograph on the file system of the Web server instead of the database. You'll get better performance by storing the image as a file with a pointer to the file in the database. However, in some cases you'll lose the convenience of having all data in one place, so it is a trade off that needs to be weighed. (Performance versus convenience).
If you want to export the image to the database, you will need to write a custom component to perform this operation. Software Artisans has a free component , which has a method for exporting binary files to a database. To retrieve the image from a database, you will want to take a look at a Knowledge Base article that discusses this process in detail.
We will store our employee information in an Access table called "Employees." The table will have the following schema:
Field Name | Data Type | Length | Description |
EmployeeID | AutoNumber | - | Number automatically assigned to employee when record is inserted. ( for the database). |
LastName | Text | 20 | Employee's last name |
FirstName | Text | 10 | Employee's first name |
Title | Text | 30 | Employee's Job Title |
PhotoFileName | Text | 50 | Filename for uploaded photograph |
Notes | Text | 255 | General information about employee |
Once the database has been created we will save it to the file system of our Web server. When working with file-based databases, it is very important that the the Internet Guest account (IUSR_<machine name>) has at least Create, Destroy, Read, and Write permissions for the folder where the database resides.
To set these permissions, complete the following steps:
We now need to create a system data source name (DSN) that references the database. A system DSN stores information about a data connection in the Windows Registry of the computer on which the DSN was created.
The Human Resources application will reside in a virtual directory called "Administration." The employee listing page will be in a virtual directory called "Corporate." In the real world, these would most likely be different servers. However, in the effort to keep this sample as simple as possible (and to allow me to meet my editorial deadlines), we'll keep this as a single-server scenario.
To create a new virtual directory, start the Microsoft Management Console (MMC) and right-click Default Web Site. Choose New/Virtual Directory. Create a virtual directory named Administration. You will need to supply a physical path to a previously created folder on your Web server's file system. When prompted to select your access permissions, choose read, script, and write permissions. Make sure that you choose write permissions; if you do not, the upload will fail.
Repeat this step and create a virtual directory for the corporate site, this time accepting only the default access permissions for the virtual directory (read and script).
With all of the preliminaries out of the way, we can get down to writing some code.
In this first section we'll force authentication on the Web page. We do this by changing the HTTP headers to force authorization. We also define the variables used on this page. Copy the following code into an ASP file called AddEmployee.ASP.
<%@ Language=VBScript %> <% Option Explicit Dim strServerURL 'Local Web Server Name including http:// protocol Dim strTargetURL 'Directory where we will upload our file to Dim strRepostURL 'Path to the page we will display after our file uploads Dim strPathToPA 'Path to the cpshost.dll Dim strPostingURL 'Action path for our form If Request.ServerVariables("LOGON_USER") = "" Then Response.Status = "401 Access Denied" Response.End End If
In the next section we use ASP Server Variables to retrieve the name of our Web server, which will make this code portable.
strServerURL = "http://" + Request.ServerVariables("SERVER_NAME") strTargetURL = strServerURL & "/Administration" strRepostURL = strServerURL & "/Administration/AddEmployeeFinish.asp" strPathToPA = strServerURL & "/Scripts/cpshost.dll" strPostingURL = strPathToPA + "?PUBLISH?" + strRepostURL %> <HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY>
The final step is to display our form. We set the enctype of the form to multipart/form-data and dynamically populate the values for the action tag and target URL.
<form enctype="multipart/form-data" action="<% = strPostingURL %>" method="POST"> <input type="hidden" name="TargetURL" value="<% = strTargetURL %>"> <center><table> <tr> <td align="left">Supply the local path to the previously scanned image file in *.gif, *.jpeg format:</td> </tr> <tr> <td align="left"><input name="my_file" type="file" size="20"></td> </tr> <tr> <td align="right"><input type="Submit" value="Next >>"></td> </tr> <table></center> </form> </BODY> </HTML>
When this page is loaded the user will be able to browse their local file system to find the photograph that they need to upload. When they click on the Next button, the form will be posted to the CPSHOST.DLL for upload processing. Once that has completed successfully, our AddEmployeeFinish.asp page will be displayed in the user's browser. As you can see, there really isn't much to this.
We will create a new ASP page called called AddEmployeeFinish.ASP. This will be our confirmation page, and it will display after the file has been uploaded. In this first section we once again force authentication on the page and define our variables. Copy the following code to your ASP file:
Option Explicit Dim strFilename 'File uploaded to web server Dim strPath 'Path up file uploaded to web server Dim I 'Counter If Request.ServerVariables("LOGON_USER") = "" Then Response.Status = "401 Access Denied" Response.End End If
Working with a multipart form is a little different than working with a standard form. We need to iterate through the form collection to retrieve the filename, file extension, and physical path. We do this in the following section of code, assigning these values to our variables.
For I = 1 To Request.Form("FileName").Count strFilename = Request.Form("FileName")(I) & Request.Form("FileExtention")(I) strPath = Request.Form("FilePath")(I) Next %>
Finally, we display a confirmation message to the user:
<HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0"> </HEAD> <BODY> <% Response.Write(strPath & strFilename & " was uploaded sucessfully") %> </BODY> </HTML>
That's it! We've uploaded our file and we are on our way to build our application. Next month we'll add additional bells and whistles, which will allow us to retrieve the information about the employee from the user, populate the database, and move the image file to the production directory.
Until then!
Jeff Sandquist is one of Microsoft's finest Canucks, and is a member of the Active Server Pages Escalation Team at Microsoft Developer Support.