Delphi XE2 DataSnap - 通过 TStream 将 JPEG 文件从服务器流式传输到客户端

发布于 2025-01-02 08:06:05 字数 586 浏览 0 评论 0原文

我编写了一个 DataSnap 服务器方法,它返回一个 TStream 对象来传输文件。客户端应用程序调用该方法并读取流来下载文件。服务器方法非常简单:

function TServerMethods.DownloadFile(sFilePath: string): TStream;
var
  strFileStream: TFileStream;
begin
  strFileStream := TFileStream.Create(sFilePath, fmOpenRead);
  Result := strFileStream;
end;

它可以很好地下载许多文件类型(PDF、GIF、BMP、ZIP、EXE),但在下载 JPG 文件时不起作用。在客户端,从方法调用返回的流对象的大小始终为 0(对于 JPG)。我可以在我的 PC 上本地成功流式传输 JPG 文件,所以这一定与 DataSnap 有关。我做了一些研究,表明 DataSnap 在幕后将流转换为 JSON,当涉及到 JPG 文件时可能会出现问题 - 有人能证实这一点吗?在客户端,我使用 TDSRESTConnection 来调用服务器方法。我意识到我可以在流式传输之前压缩 JPG 文件,但我宁愿不必这样做。

I've written a DataSnap server method that returns a TStream object to transfer a file. The client application calls the method and reads the stream to download the file. The server method is very simple :

function TServerMethods.DownloadFile(sFilePath: string): TStream;
var
  strFileStream: TFileStream;
begin
  strFileStream := TFileStream.Create(sFilePath, fmOpenRead);
  Result := strFileStream;
end;

It works fine downloading many file types (PDF, GIF, BMP, ZIP, EXE) but it doesn't work when downloading JPG files. On the client side the stream object returned from the method call is always 0 in size with JPGs. I can successfully stream JPG files locally on my PC, so it must be something to do with DataSnap. I've done some research which suggests DataSnap converts the stream to JSON behind the scenes and there could be a problem with this when it comes to JPG files - can anybody confirm this? On the client side I'm using the TDSRESTConnection to call the server method. I realise I could ZIP the JPG files before streaming, but would rather not have to do this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

去了角落 2025-01-09 08:06:05

我想我会更新我尝试解决这个问题的帖子。我从未找到使用 TStream 通过 DataSnap 传输 JPEG 文件的方法,但通过将流转换为 TJSONArray 并将其传回来实现。所以我的服务器方法现在如下所示:

function TServerMethods.DownloadJPEGFile(sFilePath: string): TJSONArray;
var
  strFileStream: TFileStream;
begin
  strFileStream := TFileStream.Create(sFilePath, fmOpenRead);
  Result := TDBXJSONTools.StreamToJSON(strFileStream, 0, strFileStream.Size);
end;

然后在客户端,我将其转换回 TStream:

strFileStream := TDBXJSONTools.JSONToStream(JSONArray);

我将其创建为纯粹用于下载 JPEG 的新服务器方法调用,因为我发现使用 TJSONArray 而不是 TStream 传输文件速度慢了 4 倍,所以我对所有其他文件类型使用原始方法。

Thought I'd update the thread on my attempts to resolve this. I never found a way to transfer a JPEG file over DataSnap using TStream, but have done it by converting the stream to a TJSONArray and passing this back instead. So my server method now looks as follows:

function TServerMethods.DownloadJPEGFile(sFilePath: string): TJSONArray;
var
  strFileStream: TFileStream;
begin
  strFileStream := TFileStream.Create(sFilePath, fmOpenRead);
  Result := TDBXJSONTools.StreamToJSON(strFileStream, 0, strFileStream.Size);
end;

then at the client end I convert back to a TStream with:

strFileStream := TDBXJSONTools.JSONToStream(JSONArray);

I have created this as a new server method call purely for downloading JPEGs, as I've found transferring the files using TJSONArray instead of TStream is as much as 4 times slower, so I use my original method for all other file types.

夏夜暖风 2025-01-09 08:06:05

只是作为更新 - 经过进一步研究,我发现这与 PC 上使用的系统区域设置有关。我使用的是“英语(英国)”,但如果我将其更改为“日本(日语)”,那么错误就会消失,文件传输工作正常。我已将其记录为 Embarcadero 的质量控制报告。

Just as an update - after further research I've found this is related to the system locale in use on the PC. I'm using 'English (United Kingdom)' but if I change this to for example 'Japan (Japanese)' then the errors disappear and the file transfer works fine. I've logged this as a QC report with Embarcadero.

毅然前行 2025-01-09 08:06:05

Embarcadero 现在已修复此问题(也会影响 .DOC 文件):

1.将 '...\RAD Studio\9.0\source\data\datasnap\Datasnap.DSClientRest.pas' 复制到您的 DataSnap Client 项目文件夹

2.将 .pas 文件添加到项目中

3.修改 Line#1288 如下

//  LResponseJSON := TJSONObject.ParseJSONValue(BytesOf(LResponseText.StringValue), 0);
LResponseJSON := TJSONObject.ParseJSONValue(BytesOf(UTF8String(LResponseText.StringValue)), 0);

4.重新构建 DataSnap REST Client 项目

5.使用 REST 运行它服务器

这解决了问题。

Embarcadero have now come back with a fix to this problem (which also affects .DOC files) :

1.Copy '...\RAD Studio\9.0\source\data\datasnap\Datasnap.DSClientRest.pas' to your DataSnap Client project folder

2.Add the .pas file to the project

3.Modify Line#1288 as below

//  LResponseJSON := TJSONObject.ParseJSONValue(BytesOf(LResponseText.StringValue), 0);
LResponseJSON := TJSONObject.ParseJSONValue(BytesOf(UTF8String(LResponseText.StringValue)), 0);

4.Rebuild DataSnap REST Client project

5.Run it with REST Server

This fixes the problem.

耳根太软 2025-01-09 08:06:05

将此行添加到您的 DownloadFile 方法中:

GetInvocationMetadata.ResponseContentType := 'image/jpeg';

Add this line to your DownloadFile method:

GetInvocationMetadata.ResponseContentType := 'image/jpeg';
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文