在Delphi rest服务器中使用文件流对象返回图像时,它不会显示在浏览器中。以下是返回图像的示例方法:
function TServerClass.Image: TFileStream;
begin
Result := TFileStream.Create('pathtofile\image.png', fmOpenRead or fmShareDenyNone);
end;
答案 0 :(得分:17)
问题是Delphi REST服务器总是将内容类型设置为text / html。当您发送其他类型的内容时,这会混淆浏览器。这是一个错误,因为大多数响应都是json,这意味着最合理的默认内容类型应该是application / json。
幸运的是,有一种方法可以从服务器方法中覆盖内容类型。
您需要将Data.DBXPlatform添加到实现的使用列表中。
此单元包含函数GetInvocationMetadata,可以访问正在构建的响应。它返回一个TDSInvocationMetadata对象,其中varius其他有用的属性具有ResponseContentType属性。
设置此属性会覆盖方法在http响应中返回的Content-Type标头。
给定的例子变为:
function TServerClass.Image: TFileStream;
begin
Result := TFileStream.Create('pathtofile\image.png', fmOpenRead or fmShareDenyNone);
GetInvocationMetadata.ResponseContentType := 'image/png';
end;
现在结果图像将在浏览器中正确显示。
答案 1 :(得分:1)
我发现这个问题也试图从DataSnap REST服务器(Delphi XE3)下载不同的文件类型(png,pdf,xlsx,docx等)到JavaScript Web客户端。 有些浏览器(例如: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上的ISAPI DLL中不起作用! 没有数据压缩(本地调试IIS),响应头是:
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代码中分配的内容处置和内容类型未显示。