昨天本來准備寫一個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, 浪費了我好幾個小時。 特記之。