Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.

how to save large array buffer from browser

Post Reply
flyfish
Posts: 4
Joined: Tue Feb 27, 2024 12:56 pm

how to save large array buffer from browser

Post by flyfish »

hi, I try to save a large array buffer from browser to local disk, in my delphi program, i registed a funciton like this:

Code: Select all

TChromillaExtension = class(TCefv8HandlerOwn)
function Execute(const name: ustring; const obj: ICefv8Value;
      const arguments: TCefv8ValueArray; var retval: ICefv8Value;
      var AException: ustring): Boolean; override;

implatement

function TChromillaExtension .Execute(const name: ustring;
  const obj: ICefv8Value; const arguments: TCefv8ValueArray;
  var retval: ICefv8Value; var AException: ustring): Boolean;
var
  //  callback, cval, rval: ICefv8Value;
  //  callbackArgs: TCefV8ValueArray;
  Params: array of Variant;
  Method: TMethod;
  I: Integer;
  L: Integer;
  ReturnValue: Variant;
begin
  Result := False;
  L := Length(arguments);
  SetLength(Params, L);
  if name = 'saveArrayBuffer' then
  begin
    SaveUInt8ArrayAsFile(arguments);
    retval := TCefv8ValueRef.NewNull;
    Result := True;
    Exit;
  end;
  ....
end;

procedure SaveUInt8ArrayAsFile(const arguments: TCefv8ValueArray);
var
  Data: TBytes;
  FileStream: TFileStream;
  keys: TStrings;
  I, iLength: Integer;
  value: ICefv8Value;
  fileName: string;
begin
  fileName := arguments[0].GetStringValue;
  value := arguments[1]; 

  if (Value <> nil) and (Value.IsObject) then
  begin
    keys := TStringList.Create;
    try
      iLength := Value.GetKeys(keys);
      SetLength(Data, iLength);

      for I := 0 to keys.Count - 1 do
        Data[I] := Value.GetValueByKey(keys[I]).GetIntValue;

      FileStream := TFileStream.Create(FileName, fmCreate);
      try
        FileStream.WriteBuffer(Data[0], Length(Data));
      finally
        FileStream.Free;
        SetLength(Data, 0);
      end;
    finally
      keys.Free;
    end;
  end;
end;
the js code like this

Code: Select all

const modifiedArrayBuffer = new ArrayBuffer(originalArrayBuffer.byteLength);
            const view = new Uint8Array(modifiedArrayBuffer);
            view.set(new Uint8Array(originalArrayBuffer));
            YChromilla.saveArrayBuffer(parseQueryString(location.search).filename, view);
 
when array buffer is small , the code is work correct, but When I try to save an ArrayBuffer with a length of 12600217, the program crashes when calling Value.GetKeys, and the memory usage spikes to 1.5GB.

Does anyone know what happened? Please let me know.I would appreciate any valuable clues.
User avatar
salvadordf
Posts: 4057
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: how to save large array buffer from browser

Post by salvadordf »

Hi,

Is this a 32 bit or 64 bit application? Try building your application with a 64 bit target.

There is a size limit in the binary parameters :
https://github.com/salvadordf/CEF4Delphi/blob/b4f492bfa12cc67eea199a06b75d772d4fa30f75/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.pas#L191

Try to handle the array buffer in a different way. There are several methods in TCefv8ValueRef and ICefv8Value related to array buffers :
https://github.com/salvadordf/CEF4Delphi/blob/master/source/uCEFv8Value.pas
flyfish
Posts: 4
Joined: Tue Feb 27, 2024 12:56 pm

Re: how to save large array buffer from browser

Post by flyfish »

hi, Thank you for your reply. My IDE version is Delphi2007, and my program is 32-bit. I have solved this problem by adding a parameters to mark the effective data length.

But I still have a question, how should the javascript call be written so that the parameters will be packed into arraybuffer type. I think the code “
for I := 0 to keys.Count - 1 do
Data := Value.GetValueByKey(keys).GetIntValue;”
will be slow when processing large amounts of data
User avatar
salvadordf
Posts: 4057
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: how to save large array buffer from browser

Post by salvadordf »

I haven't tested this but try passing the modifiedArrayBuffer instead of view as the second parameter of saveArrayBuffer in JS code.

Then read the parameters like this :

Code: Select all

  FileStream := TFileStream.Create(arguments[0].GetStringValue, fmCreate);
  try
    FileStream.WriteBuffer(arguments[1].GetArrayBufferData, arguments[1].GetArrayBufferByteLength);
  finally
    FileStream.Free;
  end;
flyfish
Posts: 4
Joined: Tue Feb 27, 2024 12:56 pm

Re: how to save large array buffer from browser

Post by flyfish »

Yes, you are right. When I use modifiedArrayBuffer instead of view, the parameter [1] becomes an ArrayBuffer. Unfortunately, ICefv8Value does not encapsulate methods like GetArrayBufferData or GetArrayBufferByteLength
So, do I have to handle this using a for loop?
User avatar
salvadordf
Posts: 4057
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: how to save large array buffer from browser

Post by salvadordf »

Update to the latest CEF4Delphi version at GitHub to see those methods :
https://github.com/salvadordf/CEF4Delphi
flyfish
Posts: 4
Joined: Tue Feb 27, 2024 12:56 pm

Re: how to save large array buffer from browser

Post by flyfish »

thank u, I got it
Post Reply