加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 在下载之前使用WinInet来识别文件大小

发布时间:2020-12-15 04:29:10 所属栏目:大数据 来源:网络整理
导读:我从第三方网站得到了源代码,解释了如何使用WinInet从互联网下载文件.我不太熟悉API,我看了看WinInet单元,但没有看到任何API调用,就像我需要的. 我正在做的是增加报告下载文件进度的能力.这个程序我已经包含在一个TThread里面,一切都很好.然而,只有一个缺失
我从第三方网站得到了源代码,解释了如何使用WinInet从互联网下载文件.我不太熟悉API,我看了看WinInet单元,但没有看到任何API调用,就像我需要的.

我正在做的是增加报告下载文件进度的能力.这个程序我已经包含在一个TThread里面,一切都很好.然而,只有一个缺失的部分:在下载之前查找源文件的总大小.

看下面我有一个评论//如何获得总大小?在我开始下载文件之前,我需要知道什么是文件的总大小.我该怎么做呢?因为这个代码似乎不知道文件的大小,直到它被完成下载 – 这使得这个添加无关紧要.

procedure TInetThread.Execute;
const
  BufferSize = 1024;
var
  hSession,hURL: HInternet;
  Buffer: array[1..BufferSize] of Byte;
  BufferLen: DWORD;
  f: File;
  S: Bool;
  D: Integer;
  T: Integer;
  procedure DoWork(const Amt: Integer);
  begin
    if assigned(FOnWork) then
      FOnWork(Self,FSource,FDest,Amt,T);
  end;
begin
  S:= False;
  try
    try
      if not DirectoryExists(ExtractFilePath(FDest)) then begin
        ForceDirectories(ExtractFilePath(FDest));
      end;
      hSession:= InternetOpen(PChar(FAppName),INTERNET_OPEN_TYPE_PRECONFIG,nil,0);
      try
        hURL:= InternetOpenURL(hSession,PChar(FSource),0);
        try
          AssignFile(f,FDest);
          Rewrite(f,1);
          T:= 0; //HOW TO GET TOTAL SIZE?
          D:= 0;
          DoWork(D);
          repeat
            InternetReadFile(hURL,@Buffer,SizeOf(Buffer),BufferLen);
            BlockWrite(f,Buffer,BufferLen);
            D:= D + BufferLen;
            DoWork(D);
          until BufferLen = 0;
          CloseFile(f);
          S:= True;
        finally
          InternetCloseHandle(hURL);
        end
      finally
        InternetCloseHandle(hSession);
      end;
    except
      on e: exception do begin
        S:= False;
      end;
    end;
  finally
    if assigned(FOnComplete) then
      FOnComplete(Self,S);
  end;
end;

解决方法

您可以使用HEAD方法,并检查Content-Length以检索远程文件的文件大小

检查这两个方法

WinInet的

如果要执行HEAD方法,则必须使用HttpOpenRequest,HttpSendRequest和HttpQueryInfo WinInet函数.

uses
 SysUtils,Windows,WinInet;

function GetWinInetError(ErrorCode:Cardinal): string;
const
   winetdll = 'wininet.dll';
var
  Len: Integer;
  Buffer: PChar;
begin
  Len := FormatMessage(
  FORMAT_MESSAGE_FROM_HMODULE or FORMAT_MESSAGE_FROM_SYSTEM or
  FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_IGNORE_INSERTS or  FORMAT_MESSAGE_ARGUMENT_ARRAY,Pointer(GetModuleHandle(winetdll)),ErrorCode,nil);
  try
    while (Len > 0) and {$IFDEF UNICODE}(CharInSet(Buffer[Len - 1],[#0..#32,'.'])) {$ELSE}(Buffer[Len - 1] in [#0..#32,'.']) {$ENDIF} do Dec(Len);
    SetString(Result,Len);
  finally
    LocalFree(HLOCAL(Buffer));
  end;
end;


procedure ParseURL(const lpszUrl: string; var Host,Resource: string);
var
  lpszScheme      : array[0..INTERNET_MAX_SCHEME_LENGTH - 1] of Char;
  lpszHostName    : array[0..INTERNET_MAX_HOST_NAME_LENGTH - 1] of Char;
  lpszUserName    : array[0..INTERNET_MAX_USER_NAME_LENGTH - 1] of Char;
  lpszPassword    : array[0..INTERNET_MAX_PASSWORD_LENGTH - 1] of Char;
  lpszUrlPath     : array[0..INTERNET_MAX_PATH_LENGTH - 1] of Char;
  lpszExtraInfo   : array[0..1024 - 1] of Char;
  lpUrlComponents : TURLComponents;
begin
  ZeroMemory(@lpszScheme,SizeOf(lpszScheme));
  ZeroMemory(@lpszHostName,SizeOf(lpszHostName));
  ZeroMemory(@lpszUserName,SizeOf(lpszUserName));
  ZeroMemory(@lpszPassword,SizeOf(lpszPassword));
  ZeroMemory(@lpszUrlPath,SizeOf(lpszUrlPath));
  ZeroMemory(@lpszExtraInfo,SizeOf(lpszExtraInfo));
  ZeroMemory(@lpUrlComponents,SizeOf(TURLComponents));

  lpUrlComponents.dwStructSize      := SizeOf(TURLComponents);
  lpUrlComponents.lpszScheme        := lpszScheme;
  lpUrlComponents.dwSchemeLength    := SizeOf(lpszScheme);
  lpUrlComponents.lpszHostName      := lpszHostName;
  lpUrlComponents.dwHostNameLength  := SizeOf(lpszHostName);
  lpUrlComponents.lpszUserName      := lpszUserName;
  lpUrlComponents.dwUserNameLength  := SizeOf(lpszUserName);
  lpUrlComponents.lpszPassword      := lpszPassword;
  lpUrlComponents.dwPasswordLength  := SizeOf(lpszPassword);
  lpUrlComponents.lpszUrlPath       := lpszUrlPath;
  lpUrlComponents.dwUrlPathLength   := SizeOf(lpszUrlPath);
  lpUrlComponents.lpszExtraInfo     := lpszExtraInfo;
  lpUrlComponents.dwExtraInfoLength := SizeOf(lpszExtraInfo);

  InternetCrackUrl(PChar(lpszUrl),Length(lpszUrl),ICU_DECODE or ICU_ESCAPE,lpUrlComponents);

  Host := lpszHostName;
  Resource := lpszUrlPath;
end;

function GetRemoteFileSize(const Url : string): Integer;
const
  sUserAgent = 'Mozilla/5.001 (windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101';

var
  hInet    : HINTERNET;
  hConnect : HINTERNET;
  hRequest : HINTERNET;
  lpdwBufferLength: DWORD;
  lpdwReserved    : DWORD;
  ServerName: string;
  Resource: string;
  ErrorCode : Cardinal;
begin
  ParseURL(Url,ServerName,Resource);
  Result:=0;

  hInet := InternetOpen(PChar(sUserAgent),0);
  if hInet=nil then
  begin
    ErrorCode:=GetLastError;
    raise Exception.Create(Format('InternetOpen Error %d Description %s',[ErrorCode,GetWinInetError(ErrorCode)]));
  end;

  try
    hConnect := InternetConnect(hInet,PChar(ServerName),INTERNET_DEFAULT_HTTP_PORT,INTERNET_SERVICE_HTTP,0);
    if hConnect=nil then
    begin
      ErrorCode:=GetLastError;
      raise Exception.Create(Format('InternetConnect Error %d Description %s',GetWinInetError(ErrorCode)]));
    end;

    try
      hRequest := HttpOpenRequest(hConnect,PChar('HEAD'),PChar(Resource),0);
        if hRequest<>nil then
        begin
          try
            lpdwBufferLength:=SizeOf(Result);
            lpdwReserved    :=0;
            if not HttpSendRequest(hRequest,0) then
            begin
              ErrorCode:=GetLastError;
              raise Exception.Create(Format('HttpOpenRequest Error %d Description %s',GetWinInetError(ErrorCode)]));
            end;

             if not HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER,@Result,lpdwBufferLength,lpdwReserved) then
             begin
              Result:=0;
              ErrorCode:=GetLastError;
              raise Exception.Create(Format('HttpQueryInfo Error %d Description %s',GetWinInetError(ErrorCode)]));
             end;
          finally
            InternetCloseHandle(hRequest);
          end;
        end
        else
        begin
          ErrorCode:=GetLastError;
          raise Exception.Create(Format('HttpOpenRequest Error %d Description %s',GetWinInetError(ErrorCode)]));
        end;
    finally
      InternetCloseHandle(hConnect);
    end;
  finally
    InternetCloseHandle(hInet);
  end;

end;

还要检查这个代码使用indy.

function GetRemoteFilesize(const Url :string) : Integer;
var
  Http: TIdHTTP;
begin
  Http := TIdHTTP.Create(nil);
  try
    Http.Head(Url);
    result:= Http.Response.ContentLength;
  finally
    Http.Free;
  end;
end;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读