通过TStream将文件上传到DataSnap REST服务器 [英] Upload file to DataSnap REST server via TStream

查看:640
本文介绍了通过TStream将文件上传到DataSnap REST服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Delphi XE2构建了一个DataSnap REST服务器,我添加了一个服务器方法,用于通过TStream上传文件:

I've built a DataSnap REST server using Delphi XE2 and I've added a server method for uploading files via TStream :

function TServerMethods.updateUploadFile(sFilename: string; UploadStream: TStream): string;

我希望能够从许多不同的客户端(Android,iOS等)调用此功能我一直在使用各种REST客户端测试该方法,例如Postman(Chrome插件)。但到目前为止,我无法接受HTTP POST正文的内容。每当我发送POST命令时,我总是得到以下响应:

I want to be able to call this from a number of different clients (Android, iOS etc) and I've been testing the method using various REST clients such as Postman (Chrome plugin). However so far I cannot get it to accept the content for the HTTP POST body. Whenever I send the POST command I always get the following response :

{"error":"Message content is not a valid JSON value."}

我尝试使用各种不同的内容类型设置但似乎没有工作。看起来DataSnap似乎坚持将内容作为JSON?我已经尝试将一些有效的JSON粘贴到内容区域,但这也给出了相同的错误响应。

I've tried using various different 'Content-Type' settings but nothing seems to work. It looks as though DataSnap is insisting on the content being JSON? I've tried pasting some valid JSON into the content area but this also gave the same error response.

是否有人成功使用TStream作为DataSnap服务器方法的输入参数?我应该以另一种方式做吗?我已经使用TStream作为输出参数多次下载文件并且效果很好,这是我第一次尝试上传。

Has anybody successfully used TStream as an input parameter for a DataSnap server method? Should I be doing it another way? I've used TStream as an output parameter for downloading files many times and it works well, this is my first attempt at uploading.

UPDATE

我做了一个快速的Delphi DataSnap客户端来测试uploadFile服务器方法,这一切都很有效。然后我使用Fiddler来检查Delphi客户端用来在内容体中发送TStream的POST命令,并注意到它是一个整数(字节)的JSON数组,例如 [37,80,68,70,45,49,46,51,13,10] 。所以我可以看到我可以修改我的Android / iOS客户端,在POST之前将二进制数据转换为这种字节数组格式,但这是我无法做到的开销。如果当TStream是一个返回参数时,DataSnap会传输原始二进制文件,为什么它不能将原始二进制文件作为输入参数进行流式传输?

I made a quick Delphi DataSnap client to test the uploadFile server method and this all works great. I then used Fiddler to examine the POST command the Delphi client uses to send the TStream in the content body, and noticed it is a JSON array of integers (bytes) e.g. [37,80,68,70,45,49,46,51,13,10]. So I can see that I could modify my Android/iOS clients to convert the binary data to this byte array format before POSTing, but this is an overhead I could do without. If DataSnap streams raw binary when TStream is a return parameter, why can't it stream raw binary as an input parameter?

推荐答案

在POST命令中向请求主体添加内容数据时,DataSnap服务器似乎坚持认为此数据始终为JSON。这就是为什么当使用TStream作为输入参数时,Delphi DataSnap客户端将流数据转换为整数(字节)的JSON数组。这种格式的效率非常低,每个字节最多3个数字加上逗号,上传的数据大小可以增长4倍。

It seems when adding content data to the request body in a POST command, DataSnap server insists that this data is always JSON. This is why when using TStream as an input parameter, the stream data is converted to a JSON array of integers (bytes) by the Delphi DataSnap client. This format is very size inefficient as with upto 3 digits per byte, plus the comma, the size of the data being uploaded can grow by as much as 4 times.

什么因此,我改为将数据编码为在Base64中上传。我的服务器方法现在看起来像这样:

What I have therefore done instead is to encode the data to upload in Base64. My server method now looks like this :

function TServerMethods.updateUploadFile(sFilename: string; Base64Data: TJSONObject): string;

注意我将Base64字符串包装在TJSONObject中。这是因为如果您只是指定一个String类型,Delphi DataSnap客户端将使用GET调用该方法并尝试将整个Base64字符串放在URL路径中,从而导致Connection Grace Gracefully错误。使用TJSONObject强制DataSnap使用POST并将数据放入内容正文中。传递的JSON对象是一对对象:

Notice I'm wrapping the Base64 string in a TJSONObject. This is because if you just specify a String type, the Delphi DataSnap client will call the method with a GET and attempt to put the whole Base64 string in the URL path, causing a 'Connection Closed Gracefully' error. Using a TJSONObject forces DataSnap to use a POST and put the data in the content body. The JSON object passed is a single pair object :

{"UploadedData":"JVBERi0xLjMNCiXi48B5SiWGTK3PaY.........."}

这样,上传的数据大小更小,传输速度更快。我仍然希望能够在内容体中传输原始数据,但DataSnap不允许这样做。

This way the size of the data uploaded is much smaller and faster to transfer. I'd still prefer to be able to stream the raw data in the content body but DataSnap doesn't allow this.

这篇关于通过TStream将文件上传到DataSnap REST服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆