8

Delphiレストサーバーでファイルストリームオブジェクトを使用して画像を返す場合、ブラウザには表示されません。画像を返すメソッドの例を次に示します。

function TServerClass.Image: TFileStream;
begin
  Result := TFileStream.Create('pathtofile\image.png', fmOpenRead or fmShareDenyNone);
end;
4

2 に答える 2

17

問題は、DelphiRESTサーバーが常にコンテンツタイプをtext/htmlに設定することです。これにより、他の種類のコンテンツを送信するときにブラウザが混乱します。ほとんどの応答はjsonであるため、これはバグです。つまり、最も賢明なデフォルトのコンテンツタイプはapplication/jsonである必要があります。

幸い、サーバーメソッド内からコンテンツタイプをオーバーライドする方法があります。

実装の使用リストにData.DBXPlatformを追加する必要があります。

このユニットには、ビルド中の応答へのアクセスを提供する関数GetInvocationMetadataが含まれています。TDSInvocationMetadataオブジェクトを返します。このオブジェクトは、さまざまな他の便利なプロパティの中でResponseContentTypeプロパティを持っています。

このプロパティを設定すると、メソッドがhttp応答で返すContent-Typeヘッダーが上書きされます。

与えられた例は次のようになります。

function TServerClass.Image: TFileStream;
begin
  Result := TFileStream.Create('pathtofile\image.png', fmOpenRead or fmShareDenyNone);
  GetInvocationMetadata.ResponseContentType := 'image/png';
end;

これで、結果の画像がブラウザに正しく表示されます。

于 2012-12-14T13:02:42.870 に答える
3

DataSnap RESTサーバー(Delphi XE3)からJavaScript Webクライアントにさまざまなファイルタイプ(png、pdf、xlsx、docxなど)をダウンロードしようとしても、この問題が見つかりました。一部のブラウザ(例:FireFox)はとにかく正しいアクションを実行しますが、すべてではありません。Internet Explorerは、正しいコンテンツタイプがないと、ダウンロードされたファイルに対する適切なアクションを認識しません。@Andersソリューションは、PDFとFirefoxを使用していたため、最初はうまく機能しているようです。しかし、IE(およびその他)でさまざまな拡張子を使用してテストしたところ、ファイルが認識されませんでした。FireBugを使用すると、Content-Typeは常に「text / html」であり、

GetInvocationMetadata.ResponseContentType := '...my assigned content type ...';

私のために働いていることがわかった回避策は次のとおりです。

ServerMethodsUnitで

var
   ContentTypeHeaderToUse: string;  // Global variable

TServerMethods1.GetFile(params: JSON):TStream;
begin
   .... processing ....
   ContentTypeHeaderToUse := '...' (assign correct content type).
end;

WebModuleUnitで

procedure TWebModule1.WebModuleAfterDispatch(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  if ContentTypeHeaderToUse<>'' then begin
    Response.ContentType := ContentTypeHeaderToUse;
    ContentTypeHeaderToUse := ''; // Reset global variable
  end;
end;

Content-Dispositionの割り当てにも同様のソリューションを使用しました。これは、ファイル名をダウンロードおよび添付ファイル/インラインモードに設定するための便利なヘッダーキーです。これを使用したコードは次のとおりです。

procedure TWebModule1.WebModuleAfterDispatch(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  if ContentDispositionHeaderToUse<>'' then begin
    Response.SetCustomHeader('content-disposition',ContentDispositionHeaderToUse);
    ContentDispositionHeaderToUse := '';
  end;
  if ContentTypeHeaderToUse<>'' then begin
    Response.ContentType := ContentTypeHeaderToUse;
    ContentTypeHeaderToUse := '';
  end;
end;

ContentDispositionHeaderToUseをサーバーメソッドの実装に割り当てます。

編集

この回避策は、データ圧縮が有効になっているIISのISAPIDLLでは機能しません。データ圧縮なし(ローカルデバッグIISIS)の場合、応答ヘッダーは次のようになります。

Connection  close
Content-Disposition inline; filename="Privacy-0.rtf.pdf"
Content-Length  150205
Content-Type    application/pdf; charset=ISO-8859-1
Pragma  dssession=28177.371935.39223,dssessionexpires=1200000

ただし、本番環境でIISが有効になっている場合、応答には次のものが含まれます。

Content-Encoding    gzip
Content-Length  11663
Content-Type    text/html
Date    Thu, 11 Sep 2014 21:56:43 GMT
Pragma  dssession=682384.52215.879906,dssessionexpires=1200000
Server  Microsoft-IIS/7.5
Vary    Accept-Encoding
X-Powered-By    ASP.NET

DataSnapコードで割り当てられたコンテンツの性質とコンテンツタイプは表示されません。

于 2014-09-09T21:35:39.647 に答える