Honestly I don't know what is missing or not to report. I am just a beginner trying to understand how things working.
But I am curious why it is not possible to change the content?
The Blob constructor accepts an iterable object, which will be the content of the blob.
The corresponding TJSBlob class definition has no such a constructor defined.
AFAICS,
there's no way to add data to the blob later, only from the constructor. Blob is indeed designed to be immutable, so that's to be expected. Therefore, without the constructor parameter, we can't make a blob containing data that can be passed to
TJSURL.createObjectURL to make a downloadable data (
File is a descendant class of Blob, that's why you can pass it alternatively).
Maybe I will be the one to contribute the change instead of reporting.
EDIT:
DoneIn the mean time, you can just do these little modification to web.pas and weborworker.pas units (+ symbol means add those lines):
TJSHTMLFile = class external name 'File' (TJSBlob)
private
FLastModified: NativeInt; external name 'lastModified';
FLastModifiedDate: TJSDate; external name 'lastModifiedDate';
FName: string; external name 'name';
public
+ constructor New(ABits: JSValue; AName: string); overload;
+ constructor New(ABits: JSValue; AName: string; AOptions: TJSObject); overload;
property lastModified: NativeInt read FLastModified;
property lastModifiedDate : TJSDate read FLastModifiedDate; deprecated;
property name: String read FName;
end;
...
TJSBlob = class external name 'Blob' (TJSEventTarget)
private
FSize: NativeInt; external name 'size';
FType: string; external name 'type';
Public
+ constructor New(AArray: JSValue); overload;
+ constructor New(AArray: JSValue; AOptions: TJSObject); overload;
procedure close;
function slice : TJSBlob; overload;
function slice(aStart : NativeInt) : TJSBlob; overload;
function slice(aStart,aEnd : NativeInt) : TJSBlob; overload;
function slice(aStart,aEnd : NativeInt; AContentType : String) : TJSBlob; overload;
function arrayBuffer : TJSPromise;
property size : NativeInt read FSize;
property _type : string read FType; deprecated;
property type_ : string read FType;
end;
Then the project code can be:
program demoreadfileinput;
uses
Web,JS;
const
DownloadFileName = 'result.txt';
var
GInput: TJSHTMLInputElement;
Goutput: TJSHTMLAnchorElement;
LReader: TJSFileReader;
LFile: TJSHTMLFile;
LFileContent: String;
begin
GInput := TJSHTMLInputElement(Document.GetElementByID('input'));
Goutput := TJSHTMLAnchorElement(Document.GetElementByID('output'));
GInput.OnChange := function (AFileInputChangeEvent: TEventListenerEvent): Boolean
begin
LFile := GInput.Files[0];
LReader := TJSFileReader.New;
LReader.OnLoad := function (AFileLoadEvent: TEventListenerEvent): Boolean
begin
LFileContent := String(TJSFileReader(AFileLoadEvent.Target).Result);
// begin edit
LFileContent := '<pre>' + LineEnding + LFileContent + LineEnding + '</pre>';
// end edit
LFile := TJSHTMLFile.New(TJSString.New(LFileContent), DownloadFileName);
Goutput.HRef := TJSURL.createObjectURL(LFile);
Goutput.Download := DownloadFileName;
Goutput.Click;
TJSURL.revokeObjectURL(Goutput.HRef);
end;
LReader.ReadAsText(LFile);
end;
end.