Jump to content
Sign in to follow this  
field

TW3Storage.LoadFile fails on "real" binary file

Recommended Posts

Hi,


 


SMS 2.2.2.4543:


 


class procedure TW3Storage.LoadFile(aFilename:String; const OnComplete:TW3StreamDataReadyEvent);

 

has a problem with loading "real" binary files (content in the result-stream gets "randomly" modified)!

 

cause:

in SmartCL.FileUtils >  TW3Storage.LoadFile TW3HttpRequest is initialized _without_ setting Element.responseType > this leads to the internal XMLHttpRequest-object assuming "Text" as the download-type, that in turn always provides the result as a string > which internally in TW3HttpRequest.ResponseAsBinaryData will always cause TVariant.IsString(mRef) to be true > and that always leads to the content being taken "through" a string!

 

As a result _very_ strange things will happen > some characters will be "destroyed", modified or ignored (basically every byte-combination leading to invalid unicode-strings will be "changed").

 

 

Suggested fix (including fixes/simplifications to TBinaryData and TW3HttpRequest):

 


class procedure TW3StorageHelper.LoadBinaryFile(aFilename:String; const OnComplete: TW3StreamDataReadyEvent);

 var

  mLoader:  TW3HttpRequest;

Begin

  mLoader:=TW3HttpRequest.Create;

  mLoader.Element.responseType:= 'arraybuffer';

  mLoader.OnDataReady:=Procedure (sender:TW3HttpRequest)

  Begin

    try

      try

        if assigned(OnComplete) then

        OnComplete(mLoader,sender.ResponseAsStream_);

      except

        on e: exception do;

      end;

    finally

      mLoader.free;

      mLoader:= nil;

    end;

  end;

  mLoader.OnError:=procedure (sender:TW3HttpRequest)

    Begin

      try

        if assigned(OnComplete) then

        OnComplete(mLoader,NIL);

      finally

        mLoader.free;

        mLoader:= nil;

      end;

    end;

 

  try

    mLoader.Get(aFilename);

  except

    on e: exception do

    Raise EW3Storage.CreateFmt(CNT_ERR_IO_FailedLoadStream,[aFilename]);

  end;

end;

 


function TW3HttpRequestHelper.ResponseAsStream_: TStream;

var

  mTemp: TBinaryData;

begin

  mTemp:= ResponseAsBinaryData_;

  if Assigned(mTemp) then

    Result:= mTemp.toStream;

end;


 


function TW3HttpRequestHelper.ResponseAsBinaryData_: TBinaryData;

var

  mView: JUint8Array;

  mRef:  THandle;

begin

  result := NIL;

  if  (FReqObj.readyState=rrsDone)

  and (FReqObj.response) then

  begin

    mRef:=FReqObj.response;

 

    if TVariant.IsString(mRef) then

    begin

      result:=TBinaryData.Create(null);

      result.Write(0,String(mRef));

    end else

    begin

      asm

        @mView = new Uint8Array(@mRef);

      end;

      result:=TBinaryData_.Create(mView);

    end;

  end;

 

end;

 


constructor TBinaryData_.Create(aHandle:TMemoryHandle);

begin

  inherited Create;

  if aHandle.defined and aHandle.valid then

  begin

    Allocate(aHandle.length);

    TMarshal.Move(aHandle,0,Handle,0,aHandle.length);

  end;

end;

 


 


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×