昨天本来准备写一个kbmMW 做webserver 的一个例子,可是在调试过程中发现不能正常显示图片文件。跟踪了很长时间
才发现是string 和 ansistring 在XE2 里面转换造成的问题,经过修改后,终于可以正常运行了。耽搁了半天时间,因此记录一下,
给同学们一个参考,以后在编程时注意一下。
原来的程序代码是这样的:
procedure TkbmMWAJAXResponseTransportStream.InternalDeliver(const AInfo:IkbmMWCustomTransportInfo);
var
i,j,k:integer;
s,sr:string; // 注意,这一块原来定义的是string;
ba:TkbmMWBytes;
hlp,hlpReq:TkbmMWHTTPTransportStreamHelper;
begin
hlp:=TkbmMWHTTPTransportStreamHelper(Helper);
hlpReq:=TkbmMWHTTPTransportStreamHelper(RequestTransportStream.Helper);
// Make sure we respond using same version as using for request.
hlp.HTTPVersion:=hlpReq.HTTPVersion;
// Check if to deliver XML Response or not.
if not (Params.Values[KBMMW_AJAX_PARAMS_XMLRESPONSE]='1') then
begin
// Check which HTTP header to send.
if Self.IsError then
begin
MimeType:='text/html';
s:=hlp.HTTPBuildErrorResponseHeaderFromStatusCode('',TkbmMWAJAXTransportStreamHelper(Helper).Header,
Self.StatusCode,Self.StatusText);
kbmMWDebugDumpString(mwdlAdvanced,mwdtTransport,kbmMWDebugWhere,'AJAX Response deliver HTML body',s);
AInfo.CloseConnectionAfterTransmit:=true;
ba:=kbmMWString2Bytes(AnsiString(s));
TProtTransport(Transport).DoTransmitBuffer(AInfo,ba,length(ba));
end
else
begin
// If the result is an array, the first element is the header instead of us generating one.
if not VarIsArray(Result) then
begin
// Send ok response with data.
sr:=Result; // result 原来的值是ansistring, 现在转换成string 类型了
s:=hlp.HTTPBuildOKResponseHeader('',TkbmMWAJAXTransportStreamHelper(Helper).Header,length(sr))+sr; // length(sr) 是unicodestring 的长度,理论上<= ansistring 的值,因此封装是就使用了一个
// 一个错误的content-length, 导致客户端与服务器端的数据不一致。
ba:=kbmMWString2Bytes(AnsiString(s));
kbmMWDebugDumpString(mwdlAdvanced,mwdtTransport,kbmMWDebugWhere,'AJAX Response deliver HTML',s);
TProtTransport(Transport).DoTransmitBuffer(AInfo,ba,length(ba));
下面是修改后的代码:
procedure TkbmMWAJAXResponseTransportStream.InternalDeliver(const AInfo:IkbmMWCustomTransportInfo);
var
i,j,k:integer;
s,sr:ansistring; // 这一块使用ansistgring, 与原始的数据类型保持一致
ba:TkbmMWBytes;
hlp,hlpReq:TkbmMWHTTPTransportStreamHelper;
begin
hlp:=TkbmMWHTTPTransportStreamHelper(Helper);
hlpReq:=TkbmMWHTTPTransportStreamHelper(RequestTransportStream.Helper);
// Make sure we respond using same version as using for request.
hlp.HTTPVersion:=hlpReq.HTTPVersion;
// Check if to deliver XML Response or not.
if not (Params.Values[KBMMW_AJAX_PARAMS_XMLRESPONSE]='1') then
begin
// Check which HTTP header to send.
if Self.IsError then
begin
MimeType:='text/html';
s:=hlp.HTTPBuildErrorResponseHeaderFromStatusCode('',TkbmMWAJAXTransportStreamHelper(Helper).Header,
Self.StatusCode,Self.StatusText);
kbmMWDebugDumpString(mwdlAdvanced,mwdtTransport,kbmMWDebugWhere,'AJAX Response deliver HTML body',s);
AInfo.CloseConnectionAfterTransmit:=true;
ba:=kbmMWString2Bytes(AnsiString(s));
TProtTransport(Transport).DoTransmitBuffer(AInfo,ba,length(ba));
end
else
begin
// If the result is an array, the first element is the header instead of us generating one.
if not VarIsArray(Result) then
begin
// Send ok response with data.
sr:=Result;
s:=hlp.HTTPBuildOKResponseHeader('',TkbmMWAJAXTransportStreamHelper(Helper).Header,length(sr))
//hlp.HTTPBuildOKResponseHeader 返回的是string, 而且是纯英文的,转换成ansistrng, 不会丢失数据。同时后面不能加sr, 不然的话,会把sr 又转换成string 了, 再转会到 ansistring, 就丢东西了
s:=s+sr; // 两个ansistring 相加, 保证数据类型一致,不产生隐形变换。
ba:=kbmMWString2Bytes(s);
经过上面修改,系统可以正常在XE2 下运行了。当然在d2007 以前,原来的代码没有问题的,看来作者没有在d2009 以后的版本没有好好测试。
好隐蔽的bug, 浪费了我好几个小时。 特记之。