考虑以下代码片段(在Delphi XE2中):
function PrepData(StrVal: string; Base64Val: AnsiString): OleVariant;
begin
Result := VarArrayCreate([0, 1], varVariant);
Result[0] := StrVal;
Result[1] := Base64Val;
end;
Base64Val
是一个二进制值,编码为Base64(所以没有null
个字节)。 (OleVariant
)结果会自动编组并在客户端应用和DataSnap服务器之间发送。
当我使用Wireshark捕获流量时,我发现StrVal
和Base64Val
都作为Unicode字符串传输。如果可以,我想避免Base64Val
的Unicode转换。我查看了所有Variant
类型,除了varString
之外没有其他任何可以传输字符数组的内容。
我发现this question显示了如何创建变量字节数组。我想我可以使用这种技术而不是使用AnsiString
。我很好奇,是否有另一种方法可以将一个非Unicode字符数据数组分配给Variant而不转换为Unicode字符串?
答案 0 :(得分:4)
Delphi的实现支持使用自定义变体类型代码在Ansiant中存储AnsiString和UnicodeString。这些代码是varString和varUString。
但是interop通常使用标准的OLE变体,而OLE字符串varOleStr是16位编码的。这似乎是你观察的原因。
如果您希望避免转换为16位文本,则需要将数据作为字节数组输入。这样做会使base64编码变得毫无意义。停止base64编码有效负载并以字节数组发送二进制文件。
答案 1 :(得分:1)
与问题中的示例保持一致,这就是我使用它的方式(使用David's answer中的代码和注释到我的问题中引用的另一个问题):
function PrepData(StrVal: string; Data: TBytes): OleVariant;
var
SafeArray: PVarArray;
begin
Result := VarArrayCreate([0, 1], varVariant);
Result[0] := StrVal;
Result[1] := VarArrayCreate([1, Length(Data)], varByte);
SafeArray := VarArrayAsPSafeArray(Result[1]);
Move(Pointer(Data)^, SafeArray.Data^, Length(Data));
end;
然后在DataSnap服务器上,我可以从OleVariant中提取二进制数据,假设Value
来自OleVariant中Variant数组的Result[1]
:
procedure GetBinaryData(Value: Variant; Result: TMemoryStream);
var
SafeArray: PVarArray;
begin
SafeArray := VarArrayAsPSafeArray(Value);
Assert(SafeArray.ElementSize=1);
Result.Clear;
Result.WriteBuffer(SafeArray.Data^, SafeArray.Bounds[0].ElementCount);
end;