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

  • Lenovo recommends Windows 8 Pro. "I dropped my laptop getting out of the taxi." This probably sounds familiar to most IT professionals. If your employees are traveling, you know their devices are in for a rough go. Whether it's a trip to the conference room or a convention out of town, any time equipment leaves a user's desk it is at risk of being put into harm's way. Stay connected at all times, whether at the office or on the go, with agile, durable, and flexible devices like the Lenovo® …

  • As the mobile enterprise marketplace expands and customer needs grow more diverse, Samsung recognizes that solution partners and developers play an essential role by continually innovating to meet their customers' needs. Samsung works to provide these developers and partners with the latest tools and resources needed to create these solutions. Read this program guide to learn how the Samsung Enterprise Alliance Program provides partners and developers with Samsung enterprise software development kits (SDKs) …

Most Popular Programming Stories

More for Developers

RSS Feeds

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