【问题标题】:Detecting the Mime-Type of a file on a remote server with INDY使用 INDY 检测远程服务器上文件的 Mime-Type
【发布时间】:2014-10-18 07:35:07
【问题描述】:

我一直在使用 Synapse 库从 Internet 下载文件,但我最近将我的应用程序转换为使用 INDY,我错过了 Synapse 库中更好的功能之一,即能够轻松获取 Mime -在将文件保存到本地计算机之前从服务器下载的文件的类型。 INDY 有这个功能吗?如果有,我该如何访问它?

【问题讨论】:

    标签: delphi mime-types indy


    【解决方案1】:

    您可以发出 HTTP HEAD 请求并检查 Content-Type 标头。在您实际GET 文件(下载)之前:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      Url: string;
      Http: TIdHTTP;
    begin
      Url := 'http://yoursite.com/yourfile.png';
      Http := TIdHTTP.Create(nil);
      try
        Http.Head(Url);
        ShowMessage(Http.Response.ContentType); // "image/png"
      finally
        Http.Free;
      end;
    end;
    

    您收到的ContentType 取决于网络服务器的实现,不保证在每台服务器上都相同。


    另一个选项是实际GET 文件并将其内容保存到内存流,例如TMemoryStream(而不是本地文件)。 Indy 提供了一个重载:

    Http.Get(Url, AStream);
    

    然后检查Http.Response.ContentType,并将流保存到文件:AStream.SaveToFile


    不确定此处的相关性,但还要注意 Indy 也可以返回/猜测本地文件的 mime 类型(给定文件扩展名)。与GetMIMETypeFromFile(使用IdGlobalProtocols)。另见here

    【讨论】:

    • 感谢您的回复。与 Synapse 的工作方式相比,这似乎是一种倒退的做事方式,但最终它的工作方式才是最重要的。
    • “这似乎是一种倒退的方式......”:我从未使用过 Synapse。您可以编辑您的问题并发布您与 Synapse 一起使用的代码,我可能会尝试猜测它是如何在那里完成的(我也相信源代码可用)。我所知道的是,任何 HTTP 客户端(Idny/Synapse/other)要么需要请求 HEAD - 它不会下载服务器内容,要么需要 GET - 它会首先下载内容(或将其流式传输到内存)。查看我的编辑。
    • 是的,使用 Synapse,您只需在文件下载时和实际保存之前检查文件的 mimtype。我猜你的流代码更接近 Synapse 的方式,但无论哪种方式都有效,所以我没有抱怨,只是不是我习惯的。
    【解决方案2】:

    或者你可以构建你的函数

    function GetMIMEType(sFile: TFileName): string;
    var aMIMEMap: TIdMIMETable;
    begin
      aMIMEMap:= TIdMIMETable.Create(true);
        try
      result:= aMIMEMap.GetFileMIMEType(sFile);
        finally
          aMIMEMap.Free;
        end;
      end;
    

    然后调用

    procedure HTTPServerGet(aThr: TIdPeerThread; reqInf: TIdHTTPRequestInfo;
                                                 respInf: TIdHTTPResponseInfo);
    var localDoc: string;
        ByteSent: Cardinal;
    begin
      //RespInfo.ContentType:= 'text/HTML';
      Writeln(Format('Command %s %s at %-10s received from %s:%d',[ReqInf.Command, ReqInf.Document, 
                           DateTimeToStr(Now),aThr.Connection.socket.binding.PeerIP,
                           aThr.Connection.socket.binding.PeerPort]));
      localDoc:= ExpandFilename(Exepath+'/web'+ReqInf.Document);
      RespInf.ContentType:= GetMIMEType(LocalDoc);
      if FileExists(localDoc) then begin
        ByteSent:= HTTPServer.ServeFile(AThr, RespInf, LocalDoc);
        Writeln(Format('Serving file %s (%d bytes/ %d bytes sent) to %s:%d at %s',
              [LocalDoc,ByteSent,FileSizeByName(LocalDoc), aThr.Connection.Socket.Binding.PeerIP,
               aThr.Connection.Socket.Binding.PeerPort, dateTimeToStr(now)]));
      end else begin
        RespInf.ResponseNo:= 404; //Not found RFC
        RespInf.ContentText:=
              '<html><head><title>Sorry WebBox Error</title></head><body><h1>' +
        RespInf.ResponseText + '</h1></body></html>';
      end; 
    end;
    

    【讨论】:

    • 我已经提到了 Indy 的 GetMIMETypeFromFile(我有点后悔我这样做了)。您的代码是报告内容类型的 服务器 端实现。 OP 询问 HTTP 客户端。但另一方面,这显示了我在回答中写的 OP “您收到的 ContentType 取决于 Web 服务器的实现,并且不保证在每台服务器上都相同”:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    • 2015-06-16
    • 2017-05-23
    • 2011-06-07
    • 1970-01-01
    相关资源
    最近更新 更多