这两天在用indy http做一个数据上传式工具,在使用TIdMultiPartFormDataStream时,老是了现“Range check error“错误,一开始以为是自己代码中有漏洞,经2个小时调试,排除自身代码问题并DEBUG跟踪INDY源代码后,发现中:
CopyTIdBytes(FInternalBuffer, 0, VBuffer, LBufferCount, LCount);
CopyTIdBytes(FInternalBuffer, LCount, FInternalBuffer, 0, LExtra)
以上两句代码,无论是何种状态在第次CopyTIdBytes时都会出现“Range Check Error"错误。进入CopyTIdBytes代码
procedure CopyTIdBytes(const ASource:TIdBytes;const ASourceIndex:integer;
var VDest:TIdBytes;const ADestIndex:integer;const ALength:integer);
begin
{$IFDEF DOTNET}
(ASource,ASourceIndex,VDest,ADestIndex,ALength);
{$ELSE}
move(ASource[ASourceIndex], VDest[ADestIndex], ALength);
{$ENDIF}
end;
发现在第二次调用CopyTIdBytes时,ALength=0时,切ASourceIndex==Length(ASource),出现数组下标越界,改正为如下代码,问题解决:
procedure CopyTIdBytes(const ASource:TIdBytes;const ASourceIndex:integer;
var VDest:TIdBytes;const ADestIndex:integer;const ALength:integer);
begin
{$IFDEF DOTNET}
(ASource,ASourceIndex,VDest,ADestIndex,ALength);
{$ELSE}
if ALength>0 then
move(ASource[ASourceIndex], VDest[ADestIndex], ALength);
{$ENDIF}
end;
另:在网上TIDHttp与TIdMultiPartFormDataStream合用的代码不是很多,下面贴一个关键片段请方家指正:
var
mds:TIdMultiPartFormDataStream;
memStream:TMemoryStream;
begin
mds:=;
memStream:=;
try
with mds do begin
//AddFormField('name','filename="E:/Ibmnbp4/报表.zip"');
AddFile('file','E:/Ibmnbp4/报表.zip','application/octet-stream');//下划线处,要根据自己的文件类型选择,我是根据Fiddler的跟踪
结果硬编码进去,如有动态识别的代码,请回复我,谢谢
AddFormField('unitID','01000135');
AddFormField('unitName','First_1(*空*)');
:=0;
(mds);
:=0;
:=RequestContentType;
(ImpData,mds,memStream);
(memStream);
end;
finally
;
;
end;
end;
此代码运用TIDHttp,TIdCookieManager和TIdMultiPartFormDataStream完成客户端向服务端提交数据,同时由于TIDHttp,TIdCookieManager的自动配合,客户/服务端通过cookie建立的Session能够自动得以维护,省了许多麻烦,令我由衷钦佩Indy 控件不愧为经典组件。