File Upload Example

This is a file upload example that sends a selected file to the example sparkle fileupload example/Demo  server included with TMSWeb.  In the TMS Example a html example is given for the client side allowing the browser to manage the upload and progress.  If you want to take control of the process the example below is a starting point.


Before you can use this example, you will have to enable CORS on the TMS uploadexample. 

Personally, I never use Windows servers.  I prefer Linux CentOS 7.  So the TMS Example upload server won't work there.  However this is a client side example so this makes it easy.  

1.  Open the example/demo fileupload from TMS and enable/add CORS to the Sparkle Server components.  
2.  Run the example server.  Make note of the URL.
3.  Create a new TMS Web application
4.  Add:  WebButton1: TWebButton,   WebMemo1: TWebMemo,  WebEdit1: TWebEdit, WebProgressBar1: TWebProgressBar,  WebFilePicker1: TWebFilePicker,   WebLabel1: TWebLabel, 
    WebWaitMessage1: TWebWaitMessage
6. add exampleFormControlFile1 to the elementID of the TWebFilePicker component
7. add exampleInputEmail1 to the elementID of the TWebEdit. Assign an email address to the text property.
5. Either use the unit below or create your own using it as an example:



unit Unit1;


interface


uses
  System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
  WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, WEBLib.ComCtrls, WEBLib.StdCtrls,
  Vcl.StdCtrls, WEBLib.WebCtrls, Vcl.Imaging.GIFImg;


type
  TForm1 = class(TWebForm)
    WebButton1: TWebButton;
    WebMemo1: TWebMemo;
    WebEdit1: TWebEdit;
    WebProgressBar1: TWebProgressBar;
    WebFilePicker1: TWebFilePicker;
    WebLabel1: TWebLabel;
    WebWaitMessage1: TWebWaitMessage;
    function _progress(Event: TJSProgressEvent): boolean;
    function _loadend(Event: TJSProgressEvent): boolean;
    function _error(Event: TJSProgressEvent): boolean;
    function _abort(Event: TJSProgressEvent): boolean;
    function _timeout(Event: TJSProgressEvent): boolean;
    function _final(Event: TJSProgressEvent): boolean;
    procedure WebButton1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


var
  Form1: TForm1;
  xhr: TJSXMLHttpRequest;
  progressCounter: Integer;
  maxfsize: LongInt;


implementation


{$R *.dfm}


//upload events you may want to capture
function TForm1._error(Event: TJSProgressEvent): boolean;
begin
    WebLabel1.Caption:= 'Upload Error!!';
end;


function TForm1._abort(Event: TJSProgressEvent): boolean;
begin
     WebLabel1.Caption:= 'Upload Aborted!';
end;


function TForm1._timeout(Event: TJSProgressEvent): boolean;
begin
    WebLabel1.Caption:= 'Upload Timed Out!';
end;


function TForm1._final(Event: TJSProgressEvent): boolean;
begin
    WebButton1.Caption := IntToStr(xhr.Status);
    WebMemo1.Lines.Add(xhr.responseText);
end;


function TForm1._progress(Event: TJSProgressEvent): boolean;
begin
// some debug data to illustrate the events
   progressCounter:= progressCounter + 1;
   WebMemo1.Lines.Add('Event Loaded: ' + IntToStr(Event.Loaded));
   WebMemo1.Lines.Add('Event Total: ' + IntToStr(Round(( Event.loaded / maxfsize ) * 100)));
   WebMemo1.Lines.Add('Event maxsize: ' + IntToStr(maxfsize));
   WebProgressbar1.Position:= (Round(( Event.loaded / maxfsize ) * 100));
end;


function TForm1._loadend(Event: TJSProgressEvent): boolean;
  begin
    WebMemo1.Lines.Add('Progress: ' + IntToStr(progressCounter));
    WebWaitMessage1.Hide;
    WebLabel1.Caption:= 'Upload Complete';
    Result:= True;
  end;


procedure TForm1.WebButton1Click(Sender: TObject);
var
  formData: JSValue;
  lmaxfsize: LongInt;


begin
  asm
    formData = new FormData();
    formData.append('fileUpload', document.getElementById('exampleFormControlFile1').files[0]);
    lmaxfsize = document.getElementById('exampleFormControlFile1').files[0].size;
    formData.append('emailAddress', document.getElementById('exampleInputEmail1').value);
  end;


  //since lmaxfsize scope is limited to this procedure, assign it to a glogal
  //to make it easy.
  maxfsize:= lmaxfsize;


  //debug to show haw many times the progress event is called
  ProgressCounter:= 0;


  //init our progress bar
  WebProgressbar1.Max:= 100;
  WebProgressbar1.Min:= 0;


  xhr := TJSXMLHttpRequest.new;


  xhr.open('POST', 'http://localhost:2001/tms/sparkle/upload');


  //add the upload event listeners needed to monirot the uploads
  xhr.upload.addEventListener('loadend', @_loadend);
  xhr.upload.addEventListener('progress',@_progress);
  xhr.upload.addEventListener('error', @_error);
  xhr.upload.addEventListener('timeout', @_timeout);
  xhr.upload.addEventListener('abort', @_abort);


  //Notice this loadend is NOT applied to the upload method
  //Only calls after everything ic complete
  xhr.addEventListener('loadend', @_final);


  //this is an option but not needed.
  WebWaitMessage1.Show;


  xhr.send(formData);
end;
end.


There is quite a bit of room for improvements.   If you want to enhance this or post your own file management changes please keep this thread alive as long as TMS allows.

For example, I use Linux stand-alone exe servers.  No fuss with Apache/httpd.  Maybe that example would be a good post here.  Or better, TMS enhance it and post it as a Gem :-)

Hope this helps.

Regards

1 Like

Frazor, I found your example very useful in figuring out the workings of XMLHttpReques and the WebFileUpload component (you used WebFilePicker). Thank you very much!