首先说下我的目的,我需要程序通过模拟提交web表单到上传页面的方式来上传一个文件到服务器
需要模拟的页面是这个
http://darx.vicp.net/program/screen/up.html
目标页面为http://darx.vicp.net/program/screen/file.php?step=upfile
该页面会把所提交的表单的各个参数都打印出来~我在网上先找了些例子~使用Indy的HTTP控件来进行开发~源代码如下
procedure TForm1.Button1Click(Sender: TObject);
var
 Request       : TMemoryStream;
 FileData      : TMemoryStream;
 Response      : TStringStream;
 tempArray     : array[0..10000] of char;
 tempString    : String;
 strFileSize   : String;
 InFile        : String;
const
 NewLine = chr(13) + chr(10);
begin
 Screen.Cursor := crHourGlass;
 InFile := 'c:\131990.jpeg';
 // Set the properties for HTTP HTTP.ProtocolVersion                := pv1_1;
 HTTP.Request.Username               := '';
 HTTP.Request.Password               := '';
 HTTP.Request.ContentEncoding        := 'multipart/form-data;boundary=-----------------------------7cf87224d2020a';
 HTTP.AllowCookies := true; try
   // create streams
   Response  := TStringStream.Create('');
   Request   := TMemoryStream.Create;
   FileData  := TMemoryStream.Create;   // load file data
   FileData.LoadFromFile( InFile );
   FileData.Seek( 0, soFromBeginning );
   // copy form data
   TempString := '';  
   TempString := TempString + '-----------------------------7cf87224d2020a' + NewLine;
   TempString := TempString + 'Content-Disposition: form-data; name="userfile"; filename="' + InFile + '"' + NewLine;
   TempString := TempString + 'Content-Type: application/octet-stream' + NewLine + NewLine;   // Add data to post
   FillChar( temparray, SizeOf( temparray ), #0 );
   strpcopy( temparray, tempstring );
   Request.Write( temparray, length(tempstring) );
   Request.Seek( 0, soFromEnd );
   //Load FileData
   Request.CopyFrom( FileData, FileData.Size );
   rc1.Text := TempString;
   // copy form data
   TempString := '';
   TempString := TempString + NewLine;
   TempString := TempString + '-----------------------------7cf87224d2020a' + NewLine;
   TempString := TempString + 'Content-Disposition: form-data; name="Submit"' + NewLine + NewLine;   TempString := TempString + 'Submit' + NewLine;
   TempString := TempString + '-----------------------------7cf87224d2020a--'  + NewLine;
   // Add data to post
   FillChar( temparray, SizeOf( temparray ), #0 );
   strpcopy( temparray, tempstring );
   Request.Write( temparray, length(tempstring) );
   // post file
   try
     HTTP.Post( 'http://darx.vicp.net/program/screen/file.php?step=upfile', Request, Response);
   except
     showmessage( 'Failed!')
   end;
   // write out debug text
   rc2.Text := Response.DataString;
   Request.SaveToFile('c:\test.txt'); finally
   Response.Free;
   Request.Free;
   FileData.Free;
   Screen.Cursor := crDefault;
 end;
end;
可是确无法成功,返回的结果是:
<pre>Array
(
    [step] => upfile
)
</pre><pre>Array
(
)
</pre> 
可见一个表单项都没有提交上去.
后来使用抓包工具对比了ie提交的数据和我提交的数据,发现HTTP Request Header都不一样
IE's Request Header:
POST /program/screen/file.php?step=upfile HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
Referer: http://darx.vicp.net/program/screen/up.html
Accept-Language: zh-cn
Content-Type: multipart/form-data; boundary=---------------------------7d4293355102ce
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon; Poco 0.31; .NET CLR 1.1.4322; .NET CLR 2.0.40607)
Host: darx.vicp.net
Content-Length: 2095
Connection: Keep-Alive
Cache-Control: no-cacheMy Request Header:
POST /program/screen/file.php?step=upfile HTTP/1.0
Connection: keep-alive
Content-Encoding: multipart/form-data;boundary=-----------------------------7cf87224d2020a
Content-Type: text/html
Content-Length: 1997
Host: darx.vicp.net
Accept: text/html, */*
User-Agent: Mozilla/3.0 (compatible; Indy Library)
非常惊讶.居然是用的HTTP1.0的协议.可是我明明设置了
 HTTP.ProtocolVersion                := pv1_1;
难道是Indy的bug?!
不解.第一次用Indy,希望有过经验的同志指点一下~谢谢!
(我用的是Delphi7 使用其自带的Indy控件)

解决方案 »

  1.   

    没有人用过么?为什么csdn只要稍稍复杂点的问题都没人回答.我的贴就结不了几次,看来只好看着性欲越来越低了
      

  2.   

    这有一段代码,你看看
    procedure TForm1.btnGoClick(Sender: TObject);
    var
      Source: TMemoryStream;
      Response: TStringStream;
    begin
      // Add the URL to the combo-box.
      if cbURL.Items.IndexOf(cbURL.Text) = -1 then
        cbURL.Items.Add(cbURL.Text);
      Screen.Cursor := crHourGlass;
      btnStop.Enabled := True;
      btnGo.Enabled := False;
      try
        memoHTML.Clear;
        // Set the properties for HTTP
        HTTP.Request.Username := edUsername.Text;
        HTTP.Request.Password := edPassword.Text;
        HTTP.Request.ProxyServer := edProxyServer.Text;
        HTTP.Request.ProxyPort := StrToIntDef(edProxyPort.Text, 80);
        HTTP.Request.ContentType := edContentType.Text;
        if cbSSL.Checked then
        begin
          HTTP.Intercept := SSL;
        end
        else
          HTTP.Intercept := nil;
        case cbMethod.ItemIndex of
          0: // Head
            begin
              HTTP.Head(cbURL.Text);
              memoHTML.Lines.Add('This is an example of some of the headers returned: ');
              memoHTML.Lines.Add('---------------------------------------------------');
              memoHTML.Lines.Add('Content-Type: ' + HTTP.Response.ContentType);
              memoHTML.Lines.Add('Date: ' + DatetoStr(HTTP.Response.Date));
              memoHTML.Lines.Add('');
              memoHTML.Lines.Add('You can view all the headers by examining HTTP.Response');
            end;
          1: // Get
            begin
              memoHTML.Lines.Text := HTTP.Get(cbURL.Text);
            end;
          2: // Post
            begin
              Response := TStringStream.Create('');
              try
                if not bPostFile then
                  HTTP.Post(cbURL.Text, mePostData.Lines, Response)
                else
                begin
                  Source := TMemoryStream.Create;
                  try
                    Source.LoadFromFile(edPostFile.Text);
                    HTTP.Post(cbURL.Text, Source, Response);
                  finally
                    Source.Free;
                  end;
                end;
                memoHTML.Lines.Text := Response.DataString;
              finally
                Response.Free;
              end;
            end;
        end;
      finally
        Screen.Cursor := crDefault;
        btnStop.Enabled := False;
        btnGo.Enabled := True;
      end;
    end;
      

  3.   

    楼上的方法没用..我用的是delphi7.郁闷啊.SSL没有定义.这个问题不会就这么完蛋了吧.我的信誉分~~~~~>_<~~~~
      

  4.   

    偶没有弄过这个东东,你可以看看它的帮助文件和DEMO:Help:
    http://www.delphibox.com/article.asp?articleid=109Demo:
    http://www.delphibox.com/article.asp?articleid=1262这里还有一个不是用Indy控件做的Http上传文件的源码,你参考一下:
    http://www.delphibox.com/article.asp?articleid=1528
      

  5.   

    http://www.delphibox.com/article.asp?articleid=1528
    我也找到了..不过也没用.协议是HTTP1.0的.
    demo也很奇怪..简单的离谱..
    郁闷啊..
      

  6.   

    关键是httpd.request.contenttype的问题,
    你参照这段代码。
    procedure TForm1.SendPostData; 
    Const 
    CRLF = #13#10; 
    Var 
    aStream: TMemoryStream; 
    Params: TMemoryStream; 
    S: String; 
    begin 
    aStream := TMemoryStream.create; 
    Params := TMemoryStream.Create; HTTP.Request.ContentType := 'multipart/form-data; 
    boundary=-----------------------------7cf87224d2020a'; try 
    S := '-----------------------------7cf87224d2020a' + CRLF + 
    'Content-Disposition: form-data; name="file1"; filename="c:abc.txt"' + 
    CRLF + 
    'Content-Type: text/plain' + CRLF + CRLF + 
    'file one content. Contant-Type can be application/octet-stream or if 
    you want you can ask your OS fot the exact type.' + CRLF + 
    '-----------------------------7cf87224d2020a' + CRLF + 
    'Content-Disposition: form-data; name="sys_return_url2"' + CRLF + CRLF + 
    'hello2' + CRLF + 
    '-----------------------------7cf87224d2020a--'; Params.Write(S[1], Length(S)); with HTTP do begin 
    try 
    HTTP.Post('http://www.mydomain.com/postexampe.cgi', Params, 
    aStream); 
    except 
    on E: Exception do 
    showmessage('Error encountered during POST: ' + E.Message); 
    end; 
    end; 
    aStream.WriteBuffer(#0' ', 1); 
    showmessage(PChar(aStream.Memory)); 
    except 
    end; 
    end; 
      

  7.   

    应该不是http版本的问题。我不懂为什么不用现成的 TIdMultipartFormData ,非要自己写。最新的Indy9.00.15中的IdMultipartFormData.pas的版本是:Rev 1.7    7/16/04 12:02:54 PM 不要用以前的版本,这个类有一些bug。
      

  8.   

    关键是怎么用呢?一个demo都没有~ 楼上的我也注意到这个类了,不过他的document实在写的太垃圾了.第一用delphi就这样,真是不好的印象啊...我自己再试下看了.
      

  9.   

    这个类用起来很简单:var 
      mps : TIdMultipartFormData;
    begin
      mps:=TIdMultipartFormData.Create;
      mps.AddFile('aFile','c:\aaa.doc');
      idHTTP1.Post('http://darx.vicp.net/program/screen/file.php?step=upfile',mps);
      ...
    end;
      

  10.   

    谢谢楼上的~问题解决了.不过我用的是AddObject :) 这个类的使用还真的简单哦~