Detecting the Mime-Type of a file on a remote serv

2020-07-18 10:45发布

问题:

I have been using the Synapse library to download files from the internet, but I have recently converted my application to use INDY instead and I am missing one of the nicer features in the Synapse library which is the ability to easily get the Mime-Type of a file that I was downloading from a server before saving it to my local machine. Does INDY have this feature and if so how do I go about accessing it?

回答1:

You can issue an HTTP HEAD request and check the Content-Type header. Before you actually GET the file (download) :

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;

The ContentType you receive back depends on the web server implementation and is not guaranteed to be the same on each and every server.


The other option, is to actually GET the file and save it's content to a memory stream such as TMemoryStream (not to a local file). Indy provides an overload:

Http.Get(Url, AStream);

Then you check the Http.Response.ContentType, and Save the stream to file: AStream.SaveToFile.


Not sure about the relevancy here, but note also that Indy can return/guess the mime type of a local file as well (given a file extension). with GetMIMETypeFromFile (uses IdGlobalProtocols). See also here.



回答2:

Or you can build your function

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

And then call

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;