Jump to content


Photo

TW3Storage.LoadFile fails on "real" binary file


  • Please log in to reply
No replies to this topic

#1 field

field
  • Members
  • 10 posts

Posted 02 January 2017 - 02:33 PM

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;
 
 

  • Igor Savkic likes this




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users