File Uploading With ISAPI

Environment: ISAPI


In this article, I will give you an easy way to upload files and work with forms using ISAPI. Uploading files with ISAPI can be useful even for ASP developers. ASP uploading is more complex and slower than ISAPI. For files over 100 Kb, ISAPI is significantly faster. I will provide you with three MFC-free classes—CQueryString, CWebForm, and CMultipartForm—for working with HTML Forms. These classes provide a fast a simple way to access any form's data. But first, let's start with the basics...

Query Strings

There are three ways that you can pass data from an HTML form your ISAPI Application, the simplest of them being in the query string. The query string is appended to the URL, with a question mark after the page name. Variables are given values using =, and appended using &; for example, isapi.dll?querystring=something&var=10. The query string is the simplest to work with; it requires only basic parsing to extract the important parts. The query string will always be available to the user, which can be good and bad. It allows the user to copy the URL, but also allows the user to view potentially sensitive data. You can pass data in a query string from a URL, or a form, which makes it very flexible. Any page can use both get and post data. To create a form that passes its data in the query string, you will need to set the method to get.

For example,

<form action=isapi.dll method=get>


The second type of form is one that posts data. The post data string is identical to the query string, but it is hidden from the user. If it is sent through a secure connection, it cannot be viewed by anyone. To set up a form that posts data, you must set the method to post.

For example,

<form action=isapi.dll method=post>

Multipart Forms

As you can imagine, it would be difficult to send a file through a query string. There is a third type of form, called a multipart form, that splits each form field up into separate parts, allowing you to send both text and files. The data the server receives from a multipart form is shown below:

Content-Disposition: form-data; name="file";
Content-Type: application/octet-stream

the data in the file.
this could be text or binary
Content-Disposition: form-data; name="Some Field"

The value of some field

As you can see, this will require a bit different parsing. The header line will be different each time. To create a multipart form, you must set the enctype to multipart/formdata, as shown below.

For example,

<form action=isapi.dll method=post enctype="multipart/form-data">

Retrieving the Form Data

IIS will give you the first 48 Kb of post data, but the rest of the data you must read from the client yourself. This is done by using the ReadClient function, which is pointed to by the ECB. Internally, I store this data in the CDataBuffer class.


CQueryString provides the base class for CWebForm and CMultipartForm. It provides the query string parsing used by itself and CWebForm. It stores all the form data in a string to a string map. The data can be accessed using the [] operator or the GetValueD, GetValueI, and GetValueL methods. These methods differ only in their return values.

For example,

std::string str = QueryString["fieldname"]; 
double d = QueryString.GetValueD("fieldname");

CQueryString also provides an IsEmpty() method to determine whether a query string was passed or whether the form was posted. CWebForm adds the ability to read the post data from the client, which is handled by the internal function ReadFormData(). CWebForm uses CQueryString's parsing method. CMultipartForm is derived from CWebForm. It uses CWebForm's ReadFormData() method, but provides its own parse method along with storage for files. The file data is contained in the CFile class.

CFile allows you to get basic information about the file, as well as save the file or retrieve a copy of the file's data. Usage of these classes is simple; all you need to do is construct the class passing it your ECB and call its parse method. The only thing you need to be careful of is that you cannot construct a CWebForm and CMultipartForm object because the second one will not be able to read data from the client. Of course, there is no reason you would ever need to.


  CQueryString QueryString( pECB );

  std::string name = QueryString["name"];
  std::string email = QueryString["email"];
  int age = QueryString.GetValueI("age");

  CWebForm Form( pECB );

  std::string name = Form["name"];
  std::string email = Form["email"];
  int age = Form.GetValueI("age");

  CMultipartForm Form( pECB );
  CFile File1;
  CFile File2;

  std::string name = Form["name"];
  std::string email = Form["email"];
  int age = Form.GetValueI("age");

  /// get the first file; we should check the name using
  /// GetFieldName to make sure it is the one we think it is
  if( Form.GetFirstFile( &File1 ) )
    File1.Save( "C:\\Uploads\\" + File1.GetClientFilename() );

  if( Form.GetNextFile( &File2 ) )
    BYTE pData = new BYTE[File2.GetBufferSize()];
    File2.GetBuffer( pData );
    // do something with pData
    delete[] pData;

That's all there is to it!


This application was written using the standard C++ library, so it should be Unix compatible. In fact, the sample application does not even include windows.h. However, I have only tested the application under Windows 2000 SP3 Pro and Server.


For IIS, you will need to give everyone write permissions in NTFS to the folder you are trying to save to. Do not give users write permission to your Web site or virtual directory! Make sure that write is unchecked in the virtual directory setup. The virtual directory will need execute scripts and executables permissions. To run the sample, place the .dll and demo.html in the same directory and browse to demo.html.


Download demo project - 111 Kb
Download source - 10 Kb


  • doesnt' work well on firefox

    Posted by gospaservice on 01/04/2012 05:37am

    It doesnt' work well on firefox: the file is uploaded, but the page of result ("you wrote:..." etc) is not displayed. How to fix it? (On Internet Explorer and Chrome it works well). Thank you so much!

  • Bug: multiple files + fix

    Posted by Legacy on 01/01/2004 12:00am

    Originally posted by: Mordred

    There's a bug in Parse() function of the CMultiPartForm class that always gets one byte less of
    the file, thus preventing you from getting more than one file.

    To fix it simply change:

    /// allocate buffer
    int nDataLen = dataend - startpos;

    int nDataLen = dataend - startpos;
    if(bFile) // we need to one byte more for strings, but not with files

    Cheers, great classes btw! :)

  • how to use CWebForm CMultipartForm in a mfc isapi ?

    Posted by Legacy on 03/25/2003 12:00am

    Originally posted by: iwaitu

    how to define ON_PARSE_COMMAND.

    can you give me a example ?

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Enterprises are increasingly looking to platform as a service (PaaS) to lower their costs and speed their time to market for new applications. Developing, deploying, and managing applications in the cloud eliminates the time and expense of managing a physical infrastructure to support them. PaaS offerings must deliver additional long-term benefits, such as a lower total cost of ownership (TCO), rapid scalability, and ease of integration, all while providing robust security and availability. This report …

  • Anthony Christie, the Chief Marketing Officer for Level Communications, is responsible for customer experience, worldwide marketing and product management. In this informative asset, he shares his insights into why a private network connection to cloud-bases applications is the right decision for your enterprise. Download now to find out more.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date