2013-08-07 130 views
1

我已经建立了采用Delphi XE2和我一个的DataSnap REST服务器已经添加了服务器方法通过T流上传文件:上传文件的DataSnap REST服务器

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

我希望能够调用这来自许多不同的客户端(Android,iOS等),我一直在使用Postman(Chrome插件)等各种REST客户端来测试该方法。但是到目前为止,我无法让它接受HTTP POST主体的内容。每当我发送POST命令我总是得到如下回应:

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

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

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

UPDATE

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

回答

3

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

因此,我所做的只是编码要在Base64中上传的数据。我的服务器方法现在看起来像这样:

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

注意我正在将T64对象中的Base64字符串包装起来。这是因为如果你只是指定一个字符串类型,Delphi DataSnap客户端将用GET调用该方法,并尝试将整个Base64字符串放在URL路径中,导致“连接关闭正常”错误。使用TJSONObject强制DataSnap使用POST并将数据放入内容主体中。传递的JSON对象是一对对象:

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

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