我知道wininet的ftpopenfile可以打开一个ftp文件,然后可以进行下载等操作,但是都说internetopernurl也可以打开一个ftp文件,但是如何把ftp的用户名和密码传进去呢?如果先用internetconnect连接上ftp,但是internetopenurl要传入的句柄是internetopen返回的,所以本着学习的态度想各位大侠请教一下这个问题。

解决方案 »

  1.   

    Delphi Internet 编程(4) 
     
    2000-08-11 15:27   
     
    FTP使用WININET  现在您阅读的是本文的第二部分,它包含了WININET的内容。正如前文提及的那样,这个部分与第一部分完全无关。  让我们先来对您在FTP部分使用WININET DLL时需要编写的代码作一个做一个概括的了解。这并不是一个详尽的学习,但却能够让您进门。为了知晓这项技术,您要做的第一件事情是明白WININET.PAS中的一些函数返回的是一个叫做HINTERNET类的指针变量:    varHINTERNET: Pointer;  这个指针扮演一个您正在使用的不同的因特网服务的句柄的角色。获得了这个句柄之后,你应当把它作为第一个参数传递给在这个进程周期[注:指FTP的整个存在时间(译者)]中调用的其他WININET函数。  您要记住的适当您在使用它的时间内要把句柄返回给系统,通常是通过调用WININET函数InternetCloseHandle来实现:    function InternetCloseHandle(hInet: HINTERNET): BOOL; stdcall;  为了让一个WININET进程开始,您调用InternetOpen :  function InternetOpen(lpszCallerName: PChar; dwAccessType: DWORD; lpszServerName:
    PChar; nServerPort: INTERNET_PORT; dwFlags: DWORD): HINTERNET; stdcall;  第一个参数时打开这个进程的应用程序的名字。您可以在这个参数中传递任何您所要的任意符串。微软公司的文献声称"这个名字作为HTTP协议中的用户代理器的名字而被使用"。这个保留的参数可以设为0或空。    varMyHandle: HINTERNET;…  beginMyHandle := InternetOpen('MyApp', 0, nil, 0, 0);end;  如果您想要关于这个函数的更多信息,从www.microsoft.com那里下载WININET.HLP。  打开了这这个进程之后,下一步是通过InternetConnect函数来连接到服务器上。    function InternetConnect(hInet: HINTERNET; // Handle from
    InternetOpenlpszServerName: PChar; // Server: i.e., www.borland.comnServerPort:
    INTERNET_PORT; // Usually 0lpszUsername: PChar; // usually anonymouslpszPassword: PChar;
    // usually your email addressdwService: DWORD; // FTP, HTTP, or Gopher?dwFlags: DWORD; //
    Usually 0dwContext: DWORD): // User defined number for callbackHINTERNET; stdcall;  这里有三个可能的可以通过dwService参数传递的自说明旗标,它们是互斥的:    INTERNET_SERVICE_FTPINTERNET_SERVICE_GOPHERINTERNET_SERVICE_HTTP  下面是dwFlags参数的选择:    INTERNET_CONNECT_FLAG_PASSIVE  这个选项仅当您在前一个参数中传递了INTERNET_SERVER_FTP才有效。这时候这个参数没有其他有效的选项。    如果这个进程成功的话会返回一个有效的指针,否则它返回空。    连接上之后  当您连接上之后,您可以调用来GetCurrentDirectory获得当前的路径的名字:    function TMyFtp.GetCurrentDirectory: string;varLen: Integer;S: string;beginLen :=
    0;ftpGetCurrentDirectory(FFTPHandle, PChar(S), Len);SetLength(S,
    Len);ftpGetCurrentDirectory(FFTPHandle, PChar(S), Len);Result := S;end;  这个函数声明如下:    function FtpGetCurrentDirectory(hFtpSession: HINTERNET; // handle from
    InternetConnectlpszCurrentDirectory: PChar; // directory returned herevar
    lpdwCurrentDirectory: DWORD): // buf size of 2nd parameterBOOL; stdcall; // True on
    success  如果您把最后一个参数设为0,那么WININET会使用这个参数来返回路径字符串的长度。接着您可以为您的字符串分配内存,也可以在调用一次这个函数来获得路径的名字。这个过程在上面的方法中已经演示过了。(注意到*设定长度*的那个调用,Delphi要求您在类似这样的情况下为新的长字符串分配内存!这是因为这个字符串必须在操作系统中指定值,而不是在Delphi应用程序中指定。结果就是Delphi不能在类似的情况下像它通常那样悄悄地为字符串分配内存)  下面是返回在特定路径下当前可用的文件的一系列函数:  
     
      

  2.   

    function GetFindDataStr(FindData: TWin32FindData): string;varS: string;Temp:
    string;begincase FindData.dwFileAttributes ofFILE_ATTRIBUTE_ARCHIVE: S := 'A';//
    FILE_ATTRIBUTE_COMPRESSED: S := 'C';FILE_ATTRIBUTE_DIRECTORY: S :=
    'D';FILE_ATTRIBUTE_HIDDEN: S := 'H';FILE_ATTRIBUTE_NORMAL: S :=
    'N';FILE_ATTRIBUTE_READONLY: S := 'R';FILE_ATTRIBUTE_SYSTEM: S :=
    'S';FILE_ATTRIBUTE_TEMPORARY: S := 'T';elseS := IntToStr(FindData.dwFileAttributes);end;S
    := S + GetDots(75);Move(FindData.CFilename[0], S[6],
    StrLen(FindData.CFileName));Temp := IntToStr(FindData.nFileSizeLow);Move(Temp[1], S[25],
    Length(Temp));Result := S;end;  function TMyFtp.FindFiles: TStringList;varFindData: TWin32FindData;FindHandle:
    HInternet;beginFindHandle := FtpFindFirstFile(FFtphandle, '*.*',FindData, 0, 0);if
    FindHandle = nil then beginResult :=
    nil;Exit;end;FCurFiles.Clear;FCurFiles.Add(GetFindDataStr(FindData));while
    InternetFindnextFile(FindHandle, @FindData)
    doFCurFiles.Add(GetFindDataStr(FindData));InternetCloseHandle(Findhandle);GetCurrentDirectory;Result
    := FCurFiles;end;  这里需要注意的关键函数是ftpFindFirstFile, InternetFindNextFile &
    InternetCloseHandle。您可以像调用Delphi函数FindFirst、FindNext & FinClose一样调用这些函数。特别的是,您使用函数ftpFindFirstFile来取得这个路径下的第一个函数。您可以不断地调用InternetFindNextFile,直到函数返回"False"为止。当这个进程结束时,调用InternetCloseHandle来通知操作系统回收与这个进程相关的内存。  I'm not going to explain this process further in this newsletter. If you want more
    information, you might look up FindFirst in the Delphi help. One final note: Unlike the
    functions mentioned in the previous paragraph, TWin32FindData is not defined in
    WININET.PAS, but instead can be found in the WIN32 help file that ships with Delphi. It is
    declared in the WINDOWS.PAS file that ships with Delphi.我不准备在这里进一步解析这个进程。如果您想要更多的信息,您可以在Delphi帮助中查找FindFirst。最后提醒一句:并不向前文提及的函数,TWin32FindData并不是在WININET.PAS中定义的,但可以在随Delphi分发的WIN32帮助文件中找到它。它在随Delphi分发的WINDOWS.PAS文件中被定义。  ==================================================================================  接受一个文件  您可以使用WININET.PAS文件中的ftpGetFile函数来从FTP取回一个文件:  function FtpGetFile(hFtpSession: HINTERNET; // Returned by
    InternetConnectlpszRemoteFile: PChar; // File to getlpszNewFile: PChar; // Where to put it
    on your PCfFailIfExists: BOOL; // Overwrite existing files?dwFlagsAndAttributes: DWORD; //
    File attribute-See CreateFile.dwFlags: DWORD; // Binary or ASCII transferdwContext:
    DWORD): // Usually zeroBOOL stdcall; // True on success  下面是一个如何使用该函数的例子:    function TMyFtp.GetFile(FTPFile, NewFile: string): Boolean;beginResult :=
    FtpGetFile(FFTPHandle, PChar(FTPFile), PChar(NewFile),False,
    File_Attribute_Normal,Ftp_Transfer_Type_Binary, 0);end;  如果要知道dwFlagsAndAttributes参数中的变量是怎样传递的,请查阅随Delphi附送的WIN32帮助文件。
      

  3.   

    典型控制  下面的Delphi控制给了你一个通过WININET FTP部分建立可视工具的起点。只是因为,这个控制可以让您是用Object
    Inspector来定义远程服务器(RemoteServer)、用户身份(UserID)和密码(Password)。    unit Ftp1;  { FTP example using WININET.PAS rather than an ACTIVEX control. Requires WININET.PAS
    andWININET.DLL. WININET.DLL you can get from Microsoft, WININET.PAS is available
    fromwww.borland.com, or with some versions ofDelphi 2.0.  You might Respond to OnNewDir events as follows:  procedure TForm1.FTP1NewDir(Sender: TObject);beginListBox1.Items :=
    MyFtp1.FindFiles; // Get the directory listend; }  interface  usesWindows, Classes, WinINet,SysUtils;  typeTMyFtp = class(TComponent)privateFContext: Integer;FINet: HInternet;FFtpHandle:
    HInternet;FCurFiles: TStringList;FServer: string;FOnNewDir: TNotifyEvent;FCurDir:
    string;FUserID: string;FPassword: string;function GetCurrentDirectory: string;procedure
    SetUpNewDir;protecteddestructor Destroy; override;publicconstructor Create(AOwner:
    TComponent); override;function Connect: Boolean;function FindFiles: TStringList;function
    ChangeDirExact(S: string): Boolean;function ChangeDirCustom(S: string): Boolean;function
    BackOneDir: Boolean;function GetFile(FTPFile, NewFile: string): Boolean;function
    SendFile1(FTPFile, NewFile: string): Boolean;function SendFile2(FTPFile, NewFile: string):
    Boolean;function CustomToFileName(S: string): string;publishedproperty CurFiles:
    TStringList read FCurFiles;property CurDir: string read FCurDir;property UserID: string
    read FUserID write FUserID;property Password: string read FPassword write
    FPassword;property Server: string read FServer write FServer;property OnNewDir:
    TNotifyEvent read FOnNewDir write FOnNewDir;end;  procedure Register;  implementation  usesDialogs;  // A few utility functions  function GetFirstToken(S: string; Token: Char): string;varTemp: string;Index:
    INteger;beginIndex := Pos(Token, S);if Index < 1 then beginGetFirstToken :=
    '';Exit;end;Dec(Index);SetLength(Temp, Index);Move(S[1], Temp[1],
    Index);GetFirstToken := Temp;end;  function StripFirstToken(S: string; Ch: Char): string;vari, Size: Integer;begini :=
    Pos(Ch, S);if i = 0 then beginStripFirstToken := S;Exit;end;Size := (Length(S) - i);Move(S[i
    + 1], S[1], Size);SetLength(S, Size);StripFirstToken := S;end;  function ReverseStr(S: string): string;varLen: Integer;Temp: String;i,j:
    Integer;beginLen := Length(S);SetLength(Temp, Len);j := Len;for i := 1 to Len do beginTemp[i]:=
    S[j];dec(j);end;ReverseStr := Temp;end;  function StripLastToken(S: string; Token: Char): string;varTemp: string;Index:
    INteger;beginSetLength(Temp, Length(S));S := ReverseStr(S);Index := Pos(Token,
    S);Inc(Index);Move(S[Index], Temp[1], Length(S) - (Index - 1));SetLength(Temp,
    Length(S) - (Index - 1));StripLastToken := ReverseStr(Temp);end;  procedure Register;beginRegisterComponents('Unleash',[TMyFtp]);end;  constructor TMyFtp.Create(AOwner: TComponent);begininherited
    Create(AOwner);FCurFiles := TStringList.Create;FINet := InternetOpen('WinINet1', 0, nil,
    0, 0);end;  destructor TMyFtp.Destroy;beginif FINet <> nil
    thenInternetCloseHandle(FINet);if FFtpHandle <> nil
    thenInternetCloseHandle(FFtpHandle);inherited Destroy;end;  function TMyFtp.Connect: Boolean;beginFContext := 255;FftpHandle :=
    InternetConnect(FINet, PChar(FServer), 0,PChar(FUserID),
    PChar(FPassWord),Internet_Service_Ftp, 0, FContext);if FFtpHandle = nil thenResult :=
    Falseelse beginSetUpNewDir;Result := True;end;end;  function TMyFtp.GetCurrentDirectory: string;varLen: Integer;S: string;beginLen :=
    0;ftpGetCurrentDirectory(FFTPHandle, PChar(S), Len);SetLength(S,
    Len);ftpGetCurrentDirectory(FFTPHandle, PChar(S), Len);Result := S;end;  procedure TMyFtp.SetUpNewDir;beginFCurDir := GetCurrentDirectory;if
    Assigned(FOnNewDir) thenFOnNewDir(Self); end;  function GetDots(NumDots: Integer): string;varS: string;i: Integer;beginS := '';for
    i := 1 to NumDots doS := S + ' ';Result := S;end;  function GetFindDataStr(FindData: TWin32FindData): string;varS: string;Temp:
    string;begincase FindData.dwFileAttributes ofFILE_ATTRIBUTE_ARCHIVE: S := 'A';//
    FILE_ATTRIBUTE_COMPRESSED: S := 'C';FILE_ATTRIBUTE_DIRECTORY: S :=
    'D';FILE_ATTRIBUTE_HIDDEN: S := 'H';FILE_ATTRIBUTE_NORMAL: S :=
    'N';FILE_ATTRIBUTE_READONLY: S := 'R';FILE_ATTRIBUTE_SYSTEM: S :=
    'S';FILE_ATTRIBUTE_TEMPORARY: S := 'T';elseS := IntToStr(FindData.dwFileAttributes);end;S
    := S + GetDots(75);Move(FindData.CFilename[0], S[6],
    StrLen(FindData.CFileName));Temp := IntToStr(FindData.nFileSizeLow);Move(Temp[1], S[25],
    Length(Temp));Result := S;end;  function TMyFtp.FindFiles: TStringList;varFindData: TWin32FindData;FindHandle:
    HInternet;beginFindHandle := FtpFindFirstFile(FFtphandle, '*.*',FindData, 0, 0);if
    FindHandle = nil then beginResult :=
    nil;Exit;end;FCurFiles.Clear;FCurFiles.Add(GetFindDataStr(FindData));while
    InternetFindnextFile(FindHandle, @FindData)
    doFCurFiles.Add(GetFindDataStr(FindData));InternetCloseHandle(Findhandle);GetCurrentDirectory;Result
    := FCurFiles;end;  function TMyFtp.CustomToFileName(S: string): string;constPreSize = 6;varTemp:
    string;TempSize: Integer;beginTemp := '';TempSize := Length(S) - PreSize; SetLength(Temp,
    TempSize);Move(S[PreSize], Temp[1], TempSize);Temp := GetFirstToken(Temp, '
    ');Result := Temp;end;  function TMyFtp.BackOneDir: Boolean;varS: string;beginS := FCurDir;S :=
    StripLastToken(S, '/');if S = '/' then beginResult := False;Exit;end;  if S <> '' then beginChangeDirExact(S);Result := True;end else
    beginChangeDirExact('/');Result := True;end;  end;  // Changes to specific directory in Sfunction TMyFtp.ChangeDirExact(S: string):
    Boolean;beginif S <> '' thenFtpSetCurrentDirectory(FFTPHandle, PChar(S));Result :=
    True;FindFiles;SetUpNewDir;end;  // Assumes S has been returned by GetFindDataString;function
    TMyFtp.ChangeDirCustom(S: string): Boolean;beginS := CustomToFileName(S);if S <> ''
    thenFtpSetCurrentDirectory(FFTPHandle, PChar(S));Result := True;FindFiles;SetUpNewDir;end;  function TMyFtp.GetFile(FTPFile, NewFile: string): Boolean;beginResult :=
    FtpGetFile(FFTPHandle, PChar(FTPFile), PChar(NewFile),False,
    File_Attribute_Normal,Ftp_Transfer_Type_Binary, 0);end;  function TMyFtp.SendFile1(FTPFile, NewFile: string): Boolean;constSize:DWord =
    3000;varTransfer: Bool;Error: DWord;S: string;beginTransfer := FtpPutFile(FFTPHandle,
    PChar(FTPFile), PChar(NewFile),Ftp_Transfer_Type_Binary, 0);  if not Transfer then beginError := GetLastError;ShowMessage(Format('Error Number:
    %d. Hex: %x', [Error, Error]));SetLength(S, Size);if not
    InternetGetLastResponseInfo(Error, PChar(S), Size) then beginError :=
    GetLastError;ShowMessage(Format('Error Number: %d. Hex: %x', [Error, Error]));end;ShowMessage(Format('Error
    Number: %d. Hex: %x Info: %s', [Error, Error, S]));end
    elseShowMessage('Success');Result := Transfer;end;  function TMyFtp.SendFile2(FTPFile, NewFile: string): Boolean;varFHandle:
    HInternet;beginFHandle := FtpOpenFile(FFTPHandle, 'sam.txt',
    GENERIC_READ,FTP_TRANSFER_TYPE_BINARY, 0);if FHandle <> nil
    thenInternetCloseHandle(FHandle)elseShowMessage('Failed');Result := True;end;  end.
      

  4.   

    你可以参考一下:http://www.cryer.co.uk/brian/delphi/wininet.htm