Delphi使用用户名和密码使用WinInet下载文件

时间:2015-02-02 22:48:53

标签: delphi wininet authorize

有很多关于如何使用WinInet下载文件的文章(这是我从中获取代码的地方),但它们似乎都比较旧和/或已关闭。没有用户名和密码的下载工作正常,但如果我用用户名和密码保护文件夹(使用VodaHost),我在尝试下载文件时不断收到身份验证错误:

401未经授权......

如果我通过网络浏览器访问,会弹出用户名/密码对话框,我可以处理好。受保护的文件夹是:

http://www.mywebsite.com/downloads

我已将服务器设置为:www.mywebsite.com并将网址设置为http://www.mywebsite.com/downloads。用户名和密码已使用网络浏览器进行验证。

我也尝试了许多排列,但我感到有些沮丧。我唯一能想到的是,这是因为服务器不受保护,而是服务器上的文件夹。服务器无法受到保护,因为它可以/可以公开访问。如果您需要更多信息,请告诉我。

有人有什么想法吗?

function Download(Server, Url, User, Pass, FileName : string): boolean;
const
  BUFFERSIZE = 4096;

var
  hSession: HINTERNET;
  hService: HINTERNET;
  hHTTP: HINTERNET;
  lpBuffer: array[0..BufferSize + 1] of Byte;
  BufferLength: DWORD;
  dwBytesRead: DWORD;
  dwSizeOfRq, Reserved, dwByteToRead: DWORD;
  localFile: file;
  fsize: DWORD;

begin
  try
    try
      // Downloads file at URL bypassing cache
      Result := False;

      // Initialize the Win32 Internet functions
      hSession := InternetOpen(PChar('Empyrean'), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ;
      // See if the session handle is valid
      if hSession = nil then
        Exit;

      hHTTP := InternetConnect(hSession, PChar(Server), INTERNET_DEFAULT_HTTP_PORT, PChar(User), PChar(Pass), INTERNET_SERVICE_HTTP, 0, 0);
      if hHTTP = nil then
        Exit;

      // InternetOpenUrl opens a handle to the Internet file using a URL. The flags indicate that the file will always
      // be read from the Internet rather than the cache
      //hService := InternetOpenUrl(hSession, pChar(url), nil, 0, INTERNET_FLAG_DONT_CACHE or INTERNET_FLAG_PRAGMA_NOCACHE or INTERNET_FLAG_RELOAD, 0);
      hService := InternetOpenUrl(hSession, pChar(url), nil, 0, INTERNET_FLAG_RELOAD, 0);

      // See if the session handle is valid
      if hService = nil then
      begin
        InternetCloseHandle(hService);
        Exit;
      end;

      HttpQueryInfo(hService, HTTP_QUERY_STATUS_CODE or HTTP_QUERY_FLAG_NUMBER, @dwByteToRead, dwSizeOfRq, Reserved);
      AssignFile(localFile, FileName);
      {$I-}
        Rewrite(localFile, 1);
     {$I+}
     if IOResult <> 0 then
      begin
        ShowMessage('Cannot create local file: ' + FileName);
        InternetCloseHandle(hService);
        Exit;
      end;
      BufferLength := BUFFERSIZE;

      // These three variables will store the size of the file, the size of the HttpQueryInfo content, and the number of bytes read in
      // total. Now determine the length of a file in bytes
      dwByteToRead := 0;
      dwSizeOfRq := 4; // BufferLength
      Reserved := 0;

      // get the file's size.
      if not HttpQueryInfo(hService, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER, @dwByteToRead, dwSizeOfRq, Reserved) then
        dwByteToRead := 0;
      FSize := 0;
      BufferLength := BUFFERSIZE;

      while (BufferLength > 0) do
      begin
      // Read data from the hService handle
        if not InternetReadFile(hService, @lpBuffer, BUFFERSIZE, BufferLength) then
          Break;
        if (BufferLength > 0) and (BufferLength <= BUFFERSIZE) then
          BlockWrite(localFile, lpBuffer, BufferLength);
        fsize := fsize + BufferLength;

      // Check the size of the remaining data. If it is zero, break
        if BufferLength > 0 then
          Result := True;
      end;

      CloseFile(localFile);
      Result := True;
    except

    end;
  finally
    // Close the Internet handle that the application has opened
    InternetCloseHandle(hService);
    InternetCloseHandle(hSession);
    InternetCloseHandle(hHTTP);
  end;

end;

2 个答案:

答案 0 :(得分:1)

在致电INTERNET_OPTION_USERNAME之前,使用InternetSetOption()INTERNET_OPTION_PASSWORD返回的句柄指定InternetConnect()InternetOpenUrl()值。

阅读文档以获取更多详细信息:

Handling Authentication

特别是:

  

即使需要身份验证,InternetOpenUrl和HttpSendRequest函数也会成功完成。不同的是,头文件和InternetReadFile中返回的数据将收到一个HTML页面,通知用户状态代码。< / p>

因此,如果InternetOpenUrl()是&#34;成功&#34;,则必须使用HttpQueryInfo()获取状态代码,如果是401,则设置用户名/密码(提示用户(如果需要)并再次尝试请求。上面的文档中有一个例子。仅当状态代码为200时,响应才会为您提供所请求的实际文件。

答案 1 :(得分:1)

感谢大家的建议。我现在通过在URL中包含用户名/密码来使用代码:

Server := 'www.myServer.com';
URL := 'http://user:pSassword@www.myserver.com/downloads/filetodownload';