昨天本来准备写一个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') thenbegin // Check which HTTP header to send.if Self.IsError thenbegin 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));endelsebegin // If the result is an array, the first element is the header instead of us generating one.if not VarIsArray(Result) thenbegin // 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') thenbegin // Check which HTTP header to send.if Self.IsError thenbegin 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));endelsebegin // If the result is an array, the first element is the header instead of us generating one.if not VarIsArray(Result) thenbegin // 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, 浪费了我好几个小时。 特记之。
时间: 2024-07-31 06:47:51