Delphi - 我可以将 InternetReadFile 用于本地文件吗?

Posted

技术标签:

【中文标题】Delphi - 我可以将 InternetReadFile 用于本地文件吗?【英文标题】:Delphi - Can I use InternetReadFile for local file? 【发布时间】:2013-01-11 09:32:37 【问题描述】:

我需要使用 WinInet 来下载文件。

我想测试它,但是当我首先检查它时,它不适用于本地文件。 (file://*)

这是在没有互联网的情况下测试程序所需要的,或者在互联网消失时进行调试......

首先我需要检查文件大小以了解 HTTPRequest 的进度,然后我需要下载文件...

正如我所见,这些函数都不适用于本地文件...

但也许我错过了一些选项,或者我使用了错误的网址...比如...

file://localhost/C:/temp/AV.GIF

有人知道吗: 一种。我可以将这些功能用于本地文件吗? 湾。如果答案是肯定的,那么我需要如何更改我的代码?

这个例子展示了我如何使用 WinInet:

function TDDWIToolObject.GetFileSize(out Size: Int64): boolean;
var
    hInet: HINTERNET;
    hConnect: HINTERNET;
    hRequest : HINTERNET;
    lpdwBufferLength: DWORD;
    lpdwReserved    : DWORD;
    ServerName: string;
    Resource: string;
    FileSizeBuffer : array[0..32] of char;
    SizeCard : Cardinal;
begin
    ParseURL(Url, ServerName, Resource);
    Result := False;
    Size := 0;

    hInet := InternetOpen(PChar(_UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
    if hInet=nil then begin
        FErrorCode := GetLastError;
        Exit;
    end;

    try

        hConnect := InternetConnect(hInet, PChar(ServerName), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
        if hConnect=nil then begin
            FErrorCode := GetLastError;
            Exit;
        end;

        try

            hRequest := HttpOpenRequest(hConnect, PChar('HEAD'), PChar(Resource), nil, nil, nil, 0, 0);
            if hRequest = nil then begin
                FErrorCode := GetLastError;
                Exit;
            end;

            try
                FillChar(FileSizeBuffer, SizeOf(FileSizeBuffer), #0);
                lpdwBufferLength := SizeOf(FileSizeBuffer);
                lpdwReserved :=0;
                if not HttpSendRequest(hRequest, nil, 0, nil, 0) then begin
                    FErrorCode := GetLastError;
                    Exit;
                end;

                if not HttpQueryInfo(
                    hRequest,
                    HTTP_QUERY_CONTENT_LENGTH,
                    @FileSizeBuffer, lpdwBufferLength, lpdwReserved) then begin

                    FErrorCode:=GetLastError;
                    Exit;
                end;

                Size := StrToInt64(StrPas(FileSizeBuffer));
                Result := True;

            finally
                InternetCloseHandle(hRequest);
            end;

        finally
            InternetCloseHandle(hConnect);
        end;

    finally
        InternetCloseHandle(hInet);
    end;

end;


function TDDWIToolObject.DownloadFile;
var
    hInet: HINTERNET;
    hFile: HINTERNET;
    pbuffer: Pointer;
    bytesRead: DWORD;
    Stm : TFileStream;
    TotalBytes : Int64;
    AbortIt : boolean;
begin
    Result := False;
    FErrorCode := -1;
    FAborted := False;
    hInet := InternetOpen(PChar(_UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
    if hInet = nil
        then begin
            FErrorCode := GetLastError;
            Exit;
        end;
    try
        hFile := InternetOpenURL(hInet, PChar(URL), PChar(FHeaders), Length(FHeaders), 0, 0);
        if hFile = nil
            then begin
                FErrorCode := GetLastError;
                Exit;
            end;
        try
            Stm := TFileStream.Create(FN, fmCreate);
            try
                GetMem(pbuffer, FBufferSize);
                try
                    TotalBytes := 0; AbortIt := False;
                    while (not FAborted) do begin
                        if not InternetReadFile(hFile, pbuffer, FBufferSize, bytesRead) then begin
                            FErrorCode := GetLastError;
                            Exit;
                        end;
                        if bytesRead > 0 then begin
                            Stm.WriteBuffer(pbuffer^, bytesRead);
                            if Assigned(FOnBytesArrived)
                                then begin
                                    inc(TotalBytes, bytesRead);
                                    FOnBytesArrived(Self, TotalBytes, AbortIt);
                                    if AbortIt
                                        then Abort;
                                end;
                        end else begin
                            break;
                        end;
                    end;
                finally
                    FreeMem(pbuffer);
                end;
                if not FAborted
                    then Result := True;
            finally
                Stm.Free;
            end;
        finally
            InternetCloseHandle(hFile);
        end;
    finally
        InternetCloseHandle(hInet);
    end;
end;

感谢您提供的所有信息、链接、文档、评论...

【问题讨论】:

如果你需要调试它——那么只需安装一些简单的 http 服务器。毕竟,如果您在与 HTTP 相关的代码中出错,您将无法使用像 fopen 这样的非 HTTP 协议对其进行调试。有很多微型 HTTP 服务器 - 只需使用它们。例如:ritlabs.com/en/products/tinyweb 【参考方案1】:

您不只是使用一些与互联网相关的功能。您使用即HttpOpenRequest - HTTP。顾名思义,这只适用于 HTTP 或 HTTP/SSL 协议。它甚至不应该适用于其他互联网协议来获取文件,如 FTP、BitTorrent、Gnutella 等。

file:// 是 URL 协议名称,它的确切含义是“不要上网,而是打开本地文件”,因此与互联网相关的功能可能无法正常工作。

当然没有办法通过它发出 GET 或 HEAD 或其他仅限 HTTP 的命令。

更重要的是,它无法帮助您调试与 HTTP 相关的错误,因为要重现这些错误将需要重复正确的 HTTP 流量序列,有时甚至可能使用给定的远程服务器版本和配置。

安装一些本地 http 服务器,如 TinyWeb、nginx 或 lighttpd - 并进行调试。

Synapse 和 mORMot 库中还有 HTTP 服务器演示,因此您甚至可以制作自己的服务器进行调试。

【讨论】:

以上是关于Delphi - 我可以将 InternetReadFile 用于本地文件吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 Delphi 中翻译语言

将参数传递给 TADOStoredProc (Delphi) 的更好方法

哪位大虾来教教我delphi怎么保存组件属性啊?

delphi 如何将属性标记为已弃用?

delphi 和 C++ Builder 中的组件?

delphi 可以将函数做为参数吗?