Chapter 2: Simple Uploads

Contents

2.1 A Simple Upload Form

The following HTML form (located in the sample file Form1.asp) enables a user to select up to three files for uploading to the server:

<HTML>
<BODY BGCOLOR="#FFFFFF">
   <FORM METHOD="POST" ENCTYPE="multipart/form-data" ACTION="UploadScript1.asp">
      <INPUT TYPE="FILE" SIZE="40" NAME="FILE1"><BR>
      <INPUT TYPE="FILE" SIZE="40" NAME="FILE2"><BR>
      <INPUT TYPE="FILE" SIZE="40" NAME="FILE3"><BR>
   <INPUT TYPE=SUBMIT VALUE="Upload!">
   </FORM>
</BODY>
</HTML>

If your browser supports HTML5, the three file items on the form above can be replaced by a single file item with the multiple attribute, as follows:

<INPUT TYPE="FILE" SIZE="40" NAME="FILE1" multiple="multiple"><BR>

Notice the ENCTYPE="multipart/form-data" attribute in the <FORM> tag. It instructs the browser to send the entire file to the server and not just the file name entered in the input text box. It is absolutely mandatory that your upload forms contain this attribute, or no uploading can be performed.

This form contains three items <INPUT TYPE="FILE"> which appear on the page as text boxes with the Browse button next to them. Each box can be used to select one file only. While the SIZE attribute of an <INPUT TYPE="FILE"> item is optional, the NAME attribute is required.

This form invokes the upload script UploadScript1.asp shown below:

<HTML>
<BODY>
<%
Set Upload = Server.CreateObject("Persits.Upload")
Count = Upload.Save("c:\upload")

Response.Write Count & " file(s) uploaded to c:\upload"
%>
</BODY>
</HTML>

The first line of the ASP script simply creates an instance of the AspUpload object. The second line calls the Save method of the component which actually performs the upload: it parses the information POSTed by the browser, figures out how many files are being uploaded, and saves them in a specified local directory on the server under their original names.

The Save method returns the number of files successfully uploaded. In case of an error this method will throw an exception.

Click the links below to run this code sample:

2.2 FILES and FORM Collections

Due to the "multipart/form-data" attribute of upload forms, your ASP script can no longer use the built-in Request.Form collection to access individual form items. AspUpload solves this problem by offering two collections of its own, Upload.Files and Upload.Form to provide access to uploaded files and text fields, respectively.

Upload.Files is a collection of UploadedFile objects which offer access to various properties and attributes of uploaded files, such as filename, path, size, hash value, etc. The UploadedFile object also offers many methods which enable you to manipulate uploaded files (copy, move, save to the database, delete, etc.) Individual items of the collection can be referenced via numeric or string indices, or iterated through via the For-Each statement.

Upload.Form is a collection of FormItem objects that represent text fields on an upload form. Upload.Form is similar to Request.Form and should be used instead of the latter in your upload script. The FormItem object provides two properties, Name and Value.

The use of the Files and Form collections is demonstrated by the sample files Form2.asp and UploadScript2.asp:

<HTML>
<BODY BGCOLOR="#FFFFFF">
   <FORM METHOD="POST" ENCTYPE="multipart/form-data" ACTION="UploadScript2.asp">
      File 1:<INPUT TYPE=FILE NAME="FILE1">
      Description 1:<INPUT TYPE=TEXT NAME="DESCR1"><BR>
      File 2:<INPUT TYPE=FILE NAME="FILE2">
      Description 2:<INPUT TYPE=TEXT NAME="DESCR2"><BR>
   <INPUT TYPE=SUBMIT VALUE="Upload!">
   </FORM>
</BODY>
</HTML>

This form contains both <INPUT TYPE=FILE> and regular <INPUT TYPE=TEXT> items. It invokes the script UploadScript2.asp:

<HTML>
<BODY

<%
Set Upload = Server.CreateObject("Persits.Upload.1")
Upload.Save "c:\upload"
%>

Files:<BR>
<%
For Each File in Upload.Files
Response.Write File.Name & "= " & File.Path & " (" & File.Size &" bytes)<BR>"
Next
%>

<P>

Other items:<BR>
<%
For Each Item in Upload.Form
Response.Write Item.Name & "= " & Item.Value & "<BR>"
Next
%>
</BODY>
</HTML>

Click the link below to run this code sample:

The output should look similar to this:

Files:
FILE1=c:\upload\File1.xls (108544 bytes)
FILE2=c:\upload\File2.zip (211687 bytes)

Other items:
DESCR1=bla bla
DESCR2=test test

IMPORTANT: The Upload.Files and Upload.Form collections are populated by the Upload.Save method. Therefore, it is incorrect to reference either collection before the Save method is called:

' Incorrect!
Upload.Save( Upload.Form("Path") )

2.3 Usage under .NET

1. Enable ASP Compatibility Mode

AspUpload 3.0 is not a native ASP.NET component. It was written specifically for classic ASP, and it uses many intrinsic ASP objects such as Request. Therefore, you must enable the classic ASP compatibility mode for all pages using AspUpload by setting the aspCompat attribute of the @Page directive to True:

<%@ Page aspCompat="True" other attributes%>

Failure to do so will result in the run-time error

There is no MTS object context

2. Use Wrapper Assembly

Create a \bin subdirectory under your ASP.NET application and place the wrapper assembly ASPUPLOADLib.dll in it. Alternatively, you can place this file in the Global Assembly Cache. The file ASPUPLOADLib.dll is included in the setup AspUpload.exe. You may also re-create this file using the command-line utility TLBIMP.

For more information, see the knowledge base article PS020704100.

The following script written in C# demonstrates AspUpload's usage under .NET:

<%@ Page aspCompat="True" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="ASPUPLOADLib" %>

<script runat="server" LANGUAGE="C#">
void Page_Load(Object Source, EventArgs E)
{
   ASPUPLOADLib.IUploadManager objUpload;
   objUpload = new ASPUPLOADLib.UploadManager();

   int Count = objUpload.Save("c:\\upload", Missing.Value, Missing.Value);

   // iterate through Files collection
   foreach( ASPUPLOADLib.IUploadedFile objFile in objUpload.Files )
   {
      txtFiles.InnerHtml += objFile.Name + "= " + objFile.Path + " (" + objFile.Size + " bytes)<BR>";
   }

   // iterate through Form collection
   foreach( ASPUPLOADLib.IFormItem objItem in objUpload.Form )
   {
      txtFormItems.InnerHtml += objItem.Name + "= " + objItem.Value + "<BR>";
   }
}
</script>

<html>
<body>
Files:<BR>
<div id="txtFiles" runat="server"/><P>
Form Items:<BR>
<div id="txtFormItems" runat="server"/><P>
</body>
</html>

Click the link below to run this code sample:

2.4 Referencing Individual File and Form Items

The previous code sample uses the For-Each loop to iterate through the Files and Form collection. It is also possible to reference individual file and form items via integer or string indices, for example:

Descr1 = Upload.Form("DESCR1")

or

Descr1 = Upload.Form(1)

When referencing an individual item from the Files collection, it is a good idea to check whether a file was actually selected via the referenced input type=file box, as follows:

Set File = Upload.Files("FILE1")
If Not File Is Nothing Then
   Response.Write File.Path
End If

The Upload.Form collection is not entirely identical to Request.Form as it handles multi-select form items such as <SELECT MULTIPLE> differently.

The sample files Form3.asp and UploadScript3.asp (not shown here) demonstrate how to handle all basic input form items with the Upload.Form collection. Click the link below to run this code sample:

2.5 Unique File Name Generation

By default, AspUpload overwrites existing files in the upload directory. In a multi-user environment, this is undesirable, as multiple users may upload files with the same name.

AspUpload can be configured to generate unique names for the files being uploaded to prevent overwriting existing files in the upload directory. This is done by setting UploadManager's OverwriteFiles property to False before calling Upload.Save, as follows:

Upload.OverwriteFiles = False

To prevent name collisions, AspUpload appends the original file name with an integer number in parentheses. For example, if the file MyFile.txt already exists in the upload directory, and another file with the same name is being uploaded, AspUpload will save the new file under the name MyFile(1).txt. If more copies of MyFile.txt are uploaded, they will be saved under the names MyFile(2).txt, MyFile(3).txt, etc.

2.6 Setting File Size Limits

AspUpload is capable of enforcing file size limits by rejecting or truncating uploaded files as specified by the SetMaxSize method. By default, any size files are accepted (as long as the total upload does not exceed 2 GB).

The SetMaxSize method expects two arguments: the maximum file size (in bytes) and a flag indicating whether a file exceeding the limit should be rejected with an error exception thrown (if set to True) or truncated (if set to False).

A value set by SetMaxSize is applied to each uploaded file individually rather than an entire upload. Since AspUpload has no way of knowing in advance how many files there are in a POST and how large they are, it will always allow the upload process to go through, even if the very first file exceeds the specified limit.

The sample files Form4.asp and UploadScript4.asp demonstrate a file upload system with file size limit enforced. Here is what the upload script looks like:

<HTML>
<BODY>
<%
Set Upload = Server.CreateObject("Persits.Upload")

' Limit file size to 50000 bytes, throw an exception if file is larger
Upload.SetMaxSize 50000, True

' Intercept all exceptions to display user-friendly error
On Error Resume Next

' Perform upload
Upload.Save "c:\upload"

' 8 is the number of "File too large" exception
If Err.Number = 8 Then
   Response.Write "Your file is too large. Please try again."
Else
   If Err <> 0 Then
      Response.Write "An error occurred: " & Err.Description
   Else
      Response.Write "Success!"
   End If
End If
%>

</BODY>
</HTML>

Click the link below to run this code sample:

2.7 Placing a Form and Script in the Same File

If the Upload.Save method is called in a script invoked directly rather than via a multipart/form-data form, the following error will occur:

Persits.Upload.1 (0x800A003D)
Wrong Content-Type. Make sure you have included the attribute ENCTYPE="multipart/form-data" in your form.

This creates a problem if you want to place both your form and the corresponding upload script in the same file. To avoid this error, set the property Upload.IgnoreNoPost to True.

The code sample BothFormAndScript.asp demonstrates the usage of this property.

<%
Set Upload = Server.CreateObject("Persits.Upload")
' Do not throw the "Wrong ContentType error first time out
Upload.IgnoreNoPost = True
Count = Upload.Save("c:\upload")

If Count > 0 Then
Response.Write Count & " file(s) uploaded."
End If
%>

<HTML>
<BODY BGCOLOR="#FFFFFF">
<h3>Simple Upload</h3>
<FORM METHOD="POST" ENCTYPE="multipart/form-data" ACTION="BothFormAndScript.asp">
<INPUT TYPE="FILE" SIZE="40" NAME="FILE1"><BR>
<INPUT TYPE="FILE" SIZE="40" NAME="FILE2"><BR>
<INPUT TYPE="FILE" SIZE="40" NAME="FILE3"><BR>
<INPUT TYPE=SUBMIT VALUE="Upload!">
</FORM>
</BODY>
</HTML>

Click the link below to run this code sample: