[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

HOWTO send large amounts of form data to ISAPI/CGI, Upload files to Pi3Web



------------------------------------------------------------------------------      
      ////// 3    // // ////// // // // ////// //////
      // //      ///// //  //  ///////   //   //  // 
     // //      // // //////   //  //   //   ////// 
------------------------------------------------------------------------------
Send large amounts of form data to ISAPI/CGI, Upload files to Pi3Web

Holger Zimmermann <zimpel@t-online.de>

V1.01                                                           17 June 1998

replaces HOWTO document from 16/June/98





------------------------------------------------------------------------------
Contents
========

1.  ISAPI
1.1 Build a client extension DLL to read large data
1.2 Debugging a client extension DLL from Delphi/C++ Builder
2.  Standard CGI (Perl)
3.  File upload with HTML-form and CGI


1. ISAPI
=========

1.1 Build a client extension DLL to read large data
---------------------------------------------------

Take good care of reading exact the pECB.cbTotalBytes of data. If you read
less bytes than indicated in pECB.cbTotalBytes a 'Connection reset by peer'
error occurs in the browser. If you try to read more bytes ReadClient never
returns.

Problem:
The pECB.cbTotalBytes holds possibly 2 bytes less than required.
If I sent a small block (all data available from pECB) the pECB.cbTotalBytes
member is always 2 bytes smaller than the pECB.cbAvailable field.

The below example code fragment shows how to make it with Delphi 3:

function HttpExtensionProc (var pECB: EXTENSION_CONTROL_BLOCK) : DWORD; export;
stdcall;
var
  Data     : Array[0..4096] of Char;
  Response : Array[0..8] of Char;
  dwLen, ToRead : DWord;
begin
  .
  .
  .
  // Do something with the pECB.cbAvailable Bytes in pECB.lpbData
  .
  .
  .
  // Possibly a bug - cbTotalBytes seems to be 2 bytes less then required
  pECB.cbTotalBytes := pECB.cbTotalBytes + 2;

  // How many bytes left to read? 
  ToRead:=pECB.cbTotalBytes - pECB.cbAvailable;

  // Our data buffer is limited to 4kByte - dwLen is set to it or the rest
  if ToRead > 4096 then dwLen := 4096 else dwLen := ToRead;

  // Call ReadClient until all Bytes are read
  while (ToRead > 0) and pECB.ReadClient(pECB.ConnID, @Data, @dwLen) do begin
    .
    .
    .
    // Do something with the dwLen Bytes in Data
    .
    .
    .
    // dwLen now contains the read count
    Dec(ToRead, dwLen);

    // Set dwLen again for the next read request
    if ToRead > 4096 then dwLen := 4096 else dwLen := ToRead;
  end;

  // Initialize the response header
  StrPCopy(Response, '200 OK');
  pECB.ServerSupportFunction(pECB.ConnID, HSE_REQ_SEND_RESPONSE_HEADER,
@Response, nil, nil);

  // We've done it
  result := HSE_STATUS_SUCCESS;
end;


1.2 Debugging a client extension DLL from Delphi/C++ Builder
------------------------------------------------------------

Menu Start|Parameters:
    host application  C:\Pi3Web\bin\enhpi3.exe
    command line      /START C:\Pi3Web\Conf\Config.pi3


2. Standard CGI (Perl)
======================

The problem is similar to ISAPI read exact ContentLength bytes and all
works fine. I tested the following with about 2.5 MBytes at once per call:

binmode STDIN;
read(STDIN, $buf, $ENV{CONTENT_LENGTH});

Don't forget to set STDIN to binary mode, if you're in Windows a EOF char
causes a broken connection otherwise. All former problems are fixed with the
binmode for STDIN. If you write $buf to a file set the Handle also to
binary mode.


3. File upload with HTML-form and CGI
======================================

Make a simple HTML-form:

<form method='POST' enctype='multipart/form-data' action='/cgi-bin/fupload.pl'>
File to upload: <input type=file name=upfile><br>
Notes about the file: <input type=text name=note><br>
<br>
<input type=submit value=Press> to upload the file!
</form>

Now make a smart script to parse the contents and rebuild the file
on the server side.

Have a look at the CGI input data:

-----------------------------2224084169055
Content-Disposition: form-data; name="upfile"; filename="c:\rfc\rfc2068.html"
Content-Type: text/html

.
.
.
-----------------------------2224084169055
Content-Disposition: form-data; name="note"


-----------------------------2224084169055--


I made some forms and scripts for basic testing.

test2.pl

Title: File Upload Form

File Upload Form

Please fill in the file-upload form:

File to upload:
Notes about the file:

to upload the file!