2017-05-03 4 views
1

私はVCLアプリケーションを作成しました。私のネットワークで動作するHTTPサーバーを作成する必要があります。Delphi IdHTTPサーバーがload html

procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; 
    ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 
var 
    a: TStringList; 
    count, logN: integer; 
begin 

if ARequestInfo.Document = '/' then 
    begin 

    AResponseInfo.ResponseNo := 200; 
    AResponseInfo.ContentText := IndexMemo.Lines.Text; 
    Memo1.Lines.Add(' Client: ' + ARequestInfo.RemoteIP); 

    end 
else 
    begin 

    AResponseInfo.ResponseNo := 200; 
    AResponseInfo.ContentText := '<html><body><b>404 NOT FOUND</b></body></html>'; 

    end; 

end; 

は今、私は唯一のテストケースif ARequestInfo.Document = '/' thenを持っていますが、後に、私はそれらの多くをする必要があります:私はあなたが下記を参照できるコードを作成しました。私はこの解決策を見つけた:

  1. ドロップ形式のメモ
  2. メモ内のHTMLを追加し、私は考えていないContextText

にメモのテキストを読み込みこれは私のフォームに20個のTMemoのようにドロップしなければならないので、これは非常に効率的であり、HTMLは維持するのが難しいでしょう。私はDeployment managerでhtmlページを読み込むことができると思った。

enter image description here

私は pagesというフォルダを作成しているDelphiのプロジェクトの同じフォルダに

、それはhtmlファイルが含まれています。私は私の質問があるので、インディHTTPサーバとHTMLページをロードする方法を確認していない:

  1. 私はどこかのフォルダ内のHTMLページを保存する必要があり、その後、インディ使用してそれらをロードしますか?
  2. [配置]ページに含まれているindyのhtmlページを読み込むことはできますか?

:私はexeファイル+ HTMLファイルを使用して、単一の(httpサーバである)exeファイルではなくフォルダを持っていると思います。 TMemoをたくさん使ってコードを保存しているので、私が見つけた解決策はかなりうまくいきますが、これは維持するのが容易ではありません。

答えて

5

まず、表示されたコードはスレッドセーフではありません。 TIdHTTPServerがマルチスレッドコンポーネントである場合、OnCommand...イベントはワーカースレッドのコンテキストでトリガされます。あなたは、安全にUIコントロールにアクセスするために、メインUIスレッドと同期する必要があります。例:

procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; 
    ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 
var 
    s: string; 
begin 
    if ARequestInfo.Document = '/' then 
    begin 
    TThread.Synchronize(nil, 
     procedure 
     begin 
     s := IndexMemo.Lines.Text; 
     Memo1.Lines.Add(' Client: ' + ARequestInfo.RemoteIP); 
     end 
    ); 

    AResponseInfo.ResponseNo := 200; 
    AResponseInfo.ContentText := s; 
    AResponseInfo.ContentType := 'text/plain'; 
    end 
    else 
    begin  
    AResponseInfo.ResponseNo := 404; 
    AResponseInfo.ContentText := '<html><body><b>404 NOT FOUND</b></body></html>'; 
    AResponseInfo.ContentType := 'text/html'; 
    end; 
end; 
  1. 私はフォルダ内のどこかにHTMLページを保存し、インディ使用してそれらをロードする必要がありますか?

  2. [配置]ページに含まれているindyでhtmlページを読み込むことはできますか?

ローカルファイルシステムからファイルを提供する場合は、ローカルファイルパスにARequestInfo.Documentプロパティの値を変換する必要があり、その後、あなたがいずれかをすることができます

  1. 要求をロードTFileStreamにファイルとAResponseInfo.ContentStreamプロパティに割り当て:

    procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; 
        ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 
    var 
        str, filename: string; 
    begin 
        str := ' Client: ' + ARequestInfo.RemoteIP + ' requesting: ' + ARequestInfo.Document; 
        TThread.Queue(nil, 
        procedure 
        begin 
         Memo1.Lines.Add(str); 
        end 
    ); 
    
        if TextStartsWith(ARequestInfo.Document, '/') then 
        begin 
        filename := Copy(ARequestInfo.Document, 2, MaxInt); 
        if filename = '' then 
         filename := 'index.txt'; 
    
        // determine local path to requested file 
        // (ProcessPath() is declared in the IdGlobalProtocols unit)... 
        filename := ProcessPath(YourDeploymentFolder, filename); 
    
        if FileExists(filename) then 
        begin 
         AResponseInfo.ResponseNo := 200; 
         AResponseInfo.ContentStream := TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite); 
         AResponseInfo.ContentType := IdHTTPServer1.MIMETable.GetFileMIMEType(filename); 
         Exit; 
        end; 
        end; 
    
        AResponseInfo.ResponseNo := 404; 
        AResponseInfo.ContentText := '<html><body><b>404 NOT FOUND</b></body></html>'; 
        AResponseInfo.ContentType := 'text/html'; 
    end; 
    
  2. TIdHTTPResponseInfo.(Smart)ServeFile()メソッドにファイルパスを渡すと、それはあなたのためのファイルを処理してみましょう:

    procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; 
        ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 
    var 
        str, filename: string; 
    begin 
        str := ' Client: ' + ARequestInfo.RemoteIP + ' requesting: ' + ARequestInfo.Document; 
        TThread.Queue(nil, 
        procedure 
        begin 
         Memo1.Lines.Add(str); 
        end 
    ); 
    
        if TextStartsWith(ARequestInfo.Document, '/') then 
        begin 
        filename := Copy(ARequestInfo.Document, 2, MaxInt); 
        if filename = '' then 
         filename := 'index.txt'; 
    
        // determine local path to requested file... 
        filename := ProcessPath(YourDeploymentFolder, filename); 
    
        AResponseInfo.SmartServeFile(AContext, ARequestInfo, filename); 
        Exit; 
        end; 
    
        AResponseInfo.ResponseNo := 404; 
        AResponseInfo.ContentText := '<html><body><b>404 NOT FOUND</b></body></html>'; 
        AResponseInfo.ContentType := 'text/html'; 
    end; 
    

私は、フォルダと(httpサーバである)、単一のexeファイルを持ちたいとしませんexe + htmlファイル。その場合

、(詳細は Resource Files Supportを参照してください。 .rcファイル、またはIDEの Resources and Imagesダイアログを使用して)コンパイル時にEXEのリソースにHTMLファイルを保存し、リソースIDに ARequestInfo.Documentを翻訳/あなたは AResponseInfo.ContentStreamオブジェクトとして使用するため TResourceStreamにロードすることができ、その名前:

procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; 
    ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 
var 
    str, resID: string; 
    strm: TResourceStream; 
begin 
    str := ' Client: ' + ARequestInfo.RemoteIP + ' requesting: ' + ARequestInfo.Document; 
    TThread.Queue(nil, 
    procedure 
    begin 
     Memo1.Lines.Add(str); 
    end 
); 

    if TextStartsWith(ARequestInfo.Document, '/') then 
    begin 
    // determine resource ID for requested file 
    // (you have to write this yourself)... 
    resID := TranslateIntoResourceID(Copy(ARequestInfo.Document, 2, MaxInt)); 
    try 
     strm := TResourceStream.Create(HInstance, resID, RT_RCDATA); 
    except 
     on E: EResNotFound do 
     strm := nil; 
    end; 

    if strm <> nil then 
    begin 
     AResponseInfo.ResponseNo := 200; 
     AResponseInfo.ContentStream := strm; 
     AResponseInfo.ContentType := 'text/html'; 
     Exit; 
    end; 
    end; 

    AResponseInfo.ResponseNo := 404; 
    AResponseInfo.ContentText := '<html><body><b>404 NOT FOUND</b></body></html>'; 
    AResponseInfo.ContentType := 'text/html'; 
end; 
+0

いつも最高ですが、あなたはここで大きな問題を解決しました。私はそれが別のスレッドで実行されているという事実については考えていませんでした。多くのありがとう –

+0

TranslateIntoResourceIDはどこから来たのですか? TextStartsWithと同じことですが、ARequestInfo.Document.Chars [0] = '/' then –

+0

"* TranslateIntoResourceIDはどこから来たのでしょうか?*" - あなた自身で書く必要があります。 "* Indyの' IdGlobal'ユニットの* TextStartsWith *と同じことです。 –

4

あなたは、リソースからコンテンツを読み込むプロジェクトメニュー、リソースとImagensに行き、あなたが必要とするリソースを追加することができます

procedure TForm2.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 
    var Page : TStringStream; 
begin 
    Page := TStringStream.Create; 
    Page.LoadFromFile('put the file path here'); 
    AResponseInfo.ResponseNo := 200; 
    AResponseInfo.ContentStream := page; 
end; 

ファイルからコンテンツを読み込むことができます。

procedure TForm2.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); 
     var page : TResourceStream; 
    begin 
     //home is the resource name 
     page := TResourceStream.Create(HInstance, 'home', RT_RCDATA); 
     AResponseInfo.ResponseNo := 200; 
     AResponseInfo.ContentStream := page; 
    end; 
+1

'TIdHTTPResponseInfo'は'(スマート)ServeFile() '利用可能な方法は、あなたが開いて、ファイルを自分で読む必要はありませんしています。 –

+1

'TileStream'の代わりに' TFileStream'(またはIndyの 'TIdReadFileExclusiveStream'または' TIdReadFileNonExclusiveStream')を使うべきです。ファイルをメモリにロードする必要はありません(もちろん**文字列**ではありません)。両方の例で、 'AResponseInfo.ContentType'を設定することを忘れないでください。 –

関連する問題