Delphi XE2 里面string 與 ansistring 轉換導致kbmMW 的一個bug


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM