🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.internet.web
Article #1543

Re: TWebRequest: How do I upload files?

#1543
From: TerryC
Date: Tue, 07 Sep 2004 14:36
153 lines
5851 bytes
For the benefit of others who may travel this rocky road after
me, here are the two working functions I finally ended up
with.  

Feel free to use and/or modify this code for your own app:

void __fastcall TWMod::WModaiPostUploadAction(TObject *Sender,
   TWebRequest *Request, TWebResponse *Response, bool &Handled)
{
   String Content;
   String TempName;
   TStringList *Fields = new TStringList;

   // Less than ~48K will fit in Request->Content
   Content = Request->Content;

   // ...so, if there is more, we have work to do
   if(Request->Content.Length() < Request->ContentLength){
      try{
         int ByteCount;
         int BytesRead = Request->Content.Length();
         int BytesToRead = Request->ContentLength - BytesRead;
   // Make room for all of it
         Content.SetLength(Request->ContentLength);
         char *DataEnd = Content.c_str() + BytesRead;
         while(BytesToRead > 0){
            ByteCount = Request->ReadClient(DataEnd, BytesToRead);
            DataEnd += ByteCount;
            BytesRead += ByteCount;
            BytesToRead = Request->ContentLength - BytesRead;
         }
      }
      catch(Exception &E){
         Response->StatusCode = 500;
         Response->Content =
               "Server exception in OFI ISAPI application.<BR><BR>"
"Message:" + E.Message;

         delete Fields;
         Handled = true;
         return;
      }
   }

   ParseFields(Content, &TempName, Fields);   // See below

   if(!TempName.Pos("*Exception")){
      int Idx = 1;

   // Here I use QueryValues passed in my app to create the
   // final file name.  The ".tmp" file created in ParseFields() 
   // is moved here.  Substitute with your own situation.

      String FileName(UploadPath + "\\" +
            Fields->Values["IssueNum"] +
            Fields->Values["Type"]);
      while(FileExists(FileName + IntToStr(Idx) +
            ExtractFileExt(Fields->Values["FileName"])))
         ++Idx;
      FileName = FileName + IntToStr(Idx) +
            ExtractFileExt(Fields->Values["FileName"]);
      if(CopyFile(TempName.c_str(), FileName.c_str(), false)){
         Response->Content = "File data saved to, \"" + 
               FileName + "\".<BR><BR>Fields: " +
               Fields->Text;
         DeleteFile(TempName.c_str());
      }
      else
         Response->Content =
               "No file data saved.<BR><BR>Fields: " +
               Fields->Text;
   }
   else
      Response->Content = "Unable to save to file, \"" + 
            TempName + "\"!";

   delete Fields;
   Handled = true;
}

void __fastcall TWMod::ParseFields(const AnsiString &Str, 
   AnsiString *TempFile, TStrings *Fields)
{
// This method probably oversimplifies parsing the fields,
// but it was sufficient for my application.

   String Content(Str);
   const String EOL("\r\n");
   const String NameTag("Content-Disposition: form-data; name=\"");
   const String FileNameTag("filename=\"");
   const String ContentTypeTag("Content-Type: ");
   const String TagEnd1("\"\r\n");
   const String TagEnd2("\";");
   String Separator;
   int Idx, Len;
   String Tag;
   String Val;

   Fields->Clear();

   Len = Content.Pos(EOL) + 1;
   Separator = Content.SubString(1, Len);

   do {
      Idx = Content.Pos(Separator) + Separator.Length();
      Len = Content.Length() - Separator.Length();
      Content = Content.SubString(Idx, Len);

      if(Content.Pos(FileNameTag) && Content.Pos(FileNameTag) < 
            Content.Pos(EOL)){	// File field
         int TmpFile;

         Idx = Content.Pos(NameTag) + NameTag.Length();
         Len = Content.Pos(TagEnd2) - Idx;
         Tag = Content.SubString(Idx, Len);

         Idx = Content.Pos(FileNameTag) + FileNameTag.Length();
         Len = Content.SubString(Idx, Content.Length() -
               Idx + 1).Pos(TagEnd1) - 1;
         Val = Content.SubString(Idx, Len);

         Idx = Content.Pos(EOL + EOL) + 3;
         Len = (Content.Pos(Separator) - 3) - Idx;
         *TempFile = String(getenv("temp")) + "\\" + "~DLD" +
               IntToStr(RandomRange(1000, 9999)) + ".tmp";
         TmpFile = FileCreate(*TempFile);
         if(TmpFile > -1){
            FileWrite(TmpFile, Content.c_str() + Idx, Len);
            FileClose(TmpFile);
         }
         else
            *TempFile = "*Exception: " + *TempFile;
      }
      else{	// Normal fields
         Idx = Content.Pos(NameTag) + NameTag.Length();
         Len = Content.Pos(TagEnd1) - Idx;
         Tag = Content.SubString(Idx, Len);

         Idx = Content.Pos(EOL + EOL) + 4;
         Len = Content.SubString(Idx, Content.Length() -
               Idx + 1).Pos(EOL) - 1;
         Val = Content.SubString(Idx, Len);
      }
      Fields->Add(Tag + "=" + Val);

   } while(Content.Pos(Separator));
}

Hope this helps somebody.  It took some work and the sole
example (in Delphi) I could find on the Web to figure it out.

-Terry
Technical Details
Message-ID: <413dc750$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.glorb.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <4137865a$1@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: feeec,13e82ec923f5058e
X-Google-Attributes: gidfeeec,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "TerryC" <terryc@sweetwaterhsa.com>
Sender: "TerryC" <terryc@sweetwaterhsa.com>
Reply-To: "TerryC" <terryc@sweetwaterhsa.com>
Subject: Re: TWebRequest: How do I upload files?
Newsgroups: borland.public.cppbuilder.internet.web
X-User-Info: 63.250.179.198     
References:  <4137865a$1@newsgroups.borland.com>
NNTP-Posting-Host: 207.105.83.66
Message-ID: <413dc750$1@newsgroups.borland.com>
Date: 7 Sep 2004 07:36:00 -0700
X-Trace: newsgroups.borland.com 1094567760 207.105.83.66 (7 Sep 2004 07:36:00 -0700)
Lines: 154
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.glorb.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail