Web Applications - File Upload Feature Pack

To purchase this Feature Pack, please click here. To purchase the File Upload, Image Upload and File/Image Download Feature Pack Bundle click here.

 

Watch Video - Quick Overview

 

Watch Video - 'File Upload' - Part 1

Watch Video - 'File Upload' - Part 2

Watch Video - 'File Upload' - Part 3

 

Watch Video - 'File Upload - User Defined' Advanced Example - Part 1

Watch Video - 'File Upload - User Defined' Advanced Example - Part 2

Watch Video - 'File Upload - User Defined' Advanced Example - Part 3

Watch Video - 'File Upload - User Defined' Advanced Example - Part 4

 

Watch Video - Uploading Files into the HTML Editor

 

 

The File Upload Feature Pack allows you to  upload files from the user's machine to the server.

 

Here are some of the things you can do with the File Upload Feature Pack:

When you have the File Upload Feature Pack installed the following new options become enabled in the Grid builder:

 

Note: If the files you want to upload are  images, the Image Upload Feature Pack might be better suited to your needs.

 

New Action Javascript Actions

The 'Upload File' action allows you to upload a single file and then either store a link to that file in a field in the current record, or embed the file in a field in the current record. The 'Upload File - User Defined Action' is for advanced users. It allows you to upload one or multiple files at once. Then, once the files have been uploaded, a user defined Xbasic function is called allowing you to process  the files that were uploaded.

Here are some of the things you might want to do using the 'File Upload - User Defined' action:

Upload File Action

The Upload File action allows you to upload one file at a time to the server and then store the uploaded file in a field in the Grid table by reference or as an embedded object.

The screenshots below show the builder.

 

First part of the File Upload Builder

 

 

 

Scrolled View of the File Upload Builder

 

Field

The builder allows you to select a Field to store the uploaded file.

When you click the smart field for the 'Field' property you get a dialog (shown below) that allows you to either select a field that is shown in the Grid, or a 'table field' - a field in the table that the Grid is based on, but that is not necessarily selected as part of the Grid.

This dialog allows you to select the field in which the uploaded file will be stored.

 

If the field you choose is a character field, then the uploaded file will be linked (i.e. the field will store a reference to the uploaded file). If you select a binary field, the uploaded file will be embedded.

There is a subtle difference between selecting a 'Grid field' and a 'Table field'. If you select a Grid field, then the field will have to be set as Updateable in the Grid properties. If you have the Security Framework turned on, then you can also specify which Groups have permission to update this field. If, on the other hand you choose a 'Table field' then you can't set field level security for the field. (You can of course set security on the button that invokes the File Upload action, so this is not a major problem.). Typically, if you want to embed the uploaded file in a field, you will not select the field to display on the Grid (there would be no point in selecting the field in the Grid - it contains binary data), and so the target field would be selected from the 'Table fields' category.

Allowed and Disallowed File Extensions

You can limit the types of files that the user can upload. You can either supply a list of allowed extensions, or a list of disallowed extensions.

Field for Object Type and Field for Object Description

If the target field is a binary field, then the builder prompts for the name of two additional fields - the field in the table that will be used to store the file type of the file you uploaded (required) and the field in the table that will store the description (i.e. filename) of the file that you uploaded (optional). So, for example, say you set the target field to 'BlobData' (a binary field) and you have another field in the table called 'BlobType' (a character field), then you might set the 'Field for Object Type' to the 'BlobType' field. If you uploaded a .pdf file, the value in the 'BlobType' field would be automatically set to .pdf. If you also specified a field for the Object Description, then filename of the file (name and extension only) will be stored in this field.

 

Upload Folder, File exists action, and Stored filename transformation expression

If the target field is a character field, these properties are displayed:

 

 

If you are uploading to a Character Field the Builder  prompts for 'Upload folder'  , 'File exists action' and 'Stored filename transformation expression'

 

The Upload Folder is the folder on the server where the uploaded file will be stored. If you specify a relative filename, the folder is in the webroot.

VERY IMPORTANT: If you have the Security Framework turned on, be sure to set the appropriate permissions for this upload folder and the files that it contains.

The File exists action can either be 'Rename' (so that it does not overwrite an existing file in the Upload Folder) or 'Overwrite' (so that any existing file would be automatically overwritten.

The Stored filename transformation expression allows you to define an Xbasic expression to transform the actual filename of the uploaded file to a value that should be stored in the target field. When you click the smart field associated with this property, the help text gives examples. For example, you might just want to store the relative filename of the uploaded file.

Maximum file size

You can specify the maximum size of the file that the server will accept. Unfortunately, it is not possible to know what the file size of the uploaded file is until after it has been uploaded. Only after the file has been uploaded can the server check the size of the file and send back a message to the client saying that the file was too large.

Auto upload

If you check this button then as soon as the user selects a file, the upload begins. Otherwise, the user must press the Upload button.

 

 

Upload File - User Defined

Watch Video - 'File Upload - User Defined' Advanced Example - Part 1

Watch Video - 'File Upload - User Defined' Advanced Example - Part 2

Watch Video - 'File Upload - User Defined' Advanced Example - Part 3

Watch Video - 'File Upload - User Defined' Advanced Example - Part 4

 

 

The 'Upload File - User Defined' action allow the user to select one or more files to upload. If the user selects multiple files to upload, all selected files are uploaded at once, when the user clicks the 'Upload' button.

For example, here is how the Select File window appears if the option to upload multiple files at once is selected. In this screenshot, the user has selected three files. There is no theoretical limit as to how many files the user can select.

Unlike the 'Upload File' action, which automatically processes the file after it has been uploaded and stores it in a field in the current record in the Grid, the 'Upload File - User Defined' action does nothing after the files have been uploaded. It simply calls an Xbasic function which you have defined. This function takes as its input an array of all of the files that were updated. Your Xbasic function can then do anything you want with the uploaded files.

For example, the uploaded file might be an Excel file that contains records which you would like to append to the table that the Grid is based on. Or you might have uploaded multiple different documents that you want to associate with the current Grid record.

When you select this action, the builder looks like this:

 

Many of the properties in this window are the same as the 'File Upload' action. There are fewer properties that the 'File Upload' action because this action does not automatically save the uploaded file and therefore has no need to know what field to store the uploaded file in, etc.

However, a key property that this action does have is the name of the Server-Side 'After upload' function. This is the Xbasic function that you define that will get called to process the uploaded files.

To get a sample prototype of this function, click the hyperlink at the bottom of the screen. The sample function prototype is shown below.

Note that the e object that is passed into the function contains a lot of information.

Some of the key properties of the e object are:

 

 

Each entry in the e.fileArray array contains information about the file that was uploaded. This information includes:

 

 

function foo as v (e as p)
'This function is called after the file(s) selected in the Upload Files dialog have been uploaded to the server.
'The function is responsible for processing each uploaded file.
'The passed in 'e' object contains these properties

'e.fileCount - the number of files that were uploaded
'e.fileArray - a property array with one entry for each uploaded file
'e.uploadFolder - the name of the folder that was specifed in the 'File Upload - User Defined' Action Builder
' - this is a relative filename in the web root where the user specified that uploaded files should be stored.
'e.uploadFolderFullyQualified - the fully qualified upload folder name.
'e.uploadProperties - Contains multiple sub-properties for all of the properties set in the Action builder.
'e.rv - Request variables
'e.tmpl - pointer to the Grid definition
'e.rtc - a pointer variable that contains run-time calculations
'e.__si - state information
'e.session - session variables
'e.rowNumber - row number of the Grid row that has focus. If val(e.rowNumber) < 0, then it is a new record row.
'e.part - either 'Grid' or 'DetailView'
'e.primaryKeyArray - an array of primary key values for the current row's primary key. If the primary key is based on a single field (or record number in the case of a .dbf table), the array will have one entry. If the primary key comprises multiple columns, the array will have an entry for each column in the primary key.


'Each entry in the e.fileArray array has these propeties (where 'i' is between 1 and e.fileCount):
'e.fileArray[i].file.characterSet - character set of the uploaded file
'e.fileArray[i].file.contentType - MIME type (e.g. 'application/octet-stream')
'e.fileArray[i].data - data that was uploaded. This will either be binary data or text data. Check the .file.dataType property
'e.fileArray[i].fileName - filename of the file on the client machine
'e.fileArray[i].encoding - For text files, specifies the encoding type
'e.fileArray[i].file.dataType = Either 'text' or 'binary'

'If you want to send any Javascript back to the browser to execute after this event has completed, you can set this property:
'e.javascript
'EXTREMELY IMPORTANT - The Javascript that is sent back to the browser is executed in the context of IFrame that contais the File Select window.
'Therefore, in order for the Javascript you send back to invoke methods of the Grid object, you must prefix all methods with 'window.parent'.
'For example: window.parent.{grid.object}.refresh()

end function
 

 

Debugging the Event

The normal technique for debugging server side events is to put a debug(1) statement in the event and then run the Grid in Working Preview mode. However, this technique will not work for File Upload because file upload is not supported in Working Preview mode. So, debugging your server side Xbasic event handler is more complicated.

Here is a technique that you can use:

 

In the first line of the function, add this code:

 

dim txt as c

txt = property_to_string(e)

dim fn as c

fn = "c:\debugdata\e.txt"

dir_create_recurse("c:\debugdata")

file.from_string(fn,txt)

 

This code will capture all of the information in the 'e' object to a file on disk. It uses the Xbasic property_to_string() function to serialize a property object.

 

Then run your Grid and upload some files.

If you look in the c:\debugdata folder you will see a file called "e.txt".

Copy your function to the clipboard. Go to the main Alpha Five Control Panel. Go to the Code tab. Create a new script. Paste the function into the script.

Then, above the function, add this code (assuming that your function is called 'myfunction'):

 

dim txt as c

txt = file.to_string("c:\debugdata\e.txt")

dim e as p

property_from_string(e,txt)

myfunction(e)

 

Finally, put this code into the function:

debug(1)

Now, run the script. You are effectively debugging the event handler using data that was captured when you uploaded the files in your test run.

 

Sample Event Handler for the 'File Upload - User Defined' Action

The Xbasic event handler shown below is the event handler that was used in the videos listed at the beginning of this section. The Xbasic event is called after the user has uploaded multiple files to the server. A record is added to a child grid for each uploaded file.

 

Here is the version for a SQL table:

function saveFiles as v (e as p)
'This function is called after the file(s) selected in the Upload Files dialog have been uploaded to the server.
'The function is responsible for processing each uploaded file.
'The passed in 'e' object contains these properties

dim count as n

'get a count of the number of files that were uploaded
count = e.filecount
dim i as n
dim arr as p

'get the array that contains all of the uploaded files
arr = e.filearray
dim cn as sql::connection
dim cs as c
cs = e.tmpl.cs.connectionstring
cn.open(cs)
dim sql as c

'construct the sql statement to insert records into the child table
sql = "insert into linkedAndEmbeddedFiles (customerId, linkedFile) values (:customerId, :filename)"

 

'create a sql arguments object
dim args as sql::arguments

 

'in order to related the new records we create in the 'linkedAndEmbeddedFiles' table the parent record

'we set the customerId in the this table to the primary key of the record in the parent grid.

'notice that the convert_type() function is called to convert the data to a numeric value (since the customerId field is a numeric field)
args.add("customerId",convert_type(e.primaryKeyArray[1],"N"))
 

'now loop through all of the entries in the array, creating a new record in the child table for each file

for i = 1 to count
    dim fn as c
    dim data as b

 

    'get the binary data that was uploaded
    data = e.fileArray[i].data

   

    'construct a filename. this is a server side filename. we want to store the files in the 'c:\myfiles' folder.
    fn = "c:\myfiles" + chr(92) + e.fileArray[i].fileName

 

    'save the binary data to a file
    file.From_blob(fn,data)


    dim fntoStore as c
    fntoStore = e.fileArray[i].fileName

   

    'set the value of the 'filename' argument.

    args.add("filename",fntoStore)


    dim flag as l
    flag = cn.Execute(sql,args)

   

    if flag = .f. then

        e.javascript = "alert('Fatal error');"

        cn.close()

        exit function

    end if
       


next i
cn.close()

 

'send back a javascript command to the browser to cause the linked content to refresh.

'notice that the Grid method must be prefixed with 'window.parent' because this callback was fired from an IFrame.
e.javascript = "window.parent.{grid.object}.refreshLinkedContent();"

end function
 

 

Here is the same script for a DBF table:

function saveFiles as v (e as p)
'This function is called after the file(s) selected in the Upload Files dialog have been uploaded to the server.
'The function is responsible for processing each uploaded file.
'The passed in 'e' object contains these properties

dim count as n

'get a count of the number of files that were uploaded
count = e.filecount
dim i as n
dim arr as p

'get the array that contains all of the uploaded files
arr = e.filearray
 

 

dim tbl as p

tbl = table.open("[PathAlias.ADB_Path]\linkedObjects.dbf")

 

'now loop through all of the entries in the array, creating a new record in the child table for each file

for i = 1 to count
    dim fn as c
    dim data as b

 

    'get the binary data that was uploaded
    data = e.fileArray[i].data

   

    'construct a filename. this is a server side filename. we want to store the files in the 'c:\myfiles' folder.
    fn = "c:\myfiles" + chr(92) + e.fileArray[i].fileName

 

    'save the binary data to a file
    file.From_blob(fn,data)


    dim fntoStore as c
    fntoStore = e.fileArray[i].fileName

 

    tbl.enter_begin()

    tbl.customerId = convert_type(e.primaryKeyArray[1],"N")

    tbl.linkedFile = fntoStore

    tbl.enter_end(.t.)

   


next i
tbl.close()

 

 

'send back a javascript command to the browser to cause the linked content to refresh.

'notice that the Grid method must be prefixed with 'window.parent' because this callback was fired from an IFrame.
e.javascript = "window.parent.{grid.object}.refreshLinkedContent();"

end function
 

 

Uploading Files and Linking Them in the HTML Editor

Watch Video - Uploading Images into the HTML Editor

 

Important: This feature is not supported in Working Preview mode.

 

If the File Upload Feature Pack is installed, then the Field Properties dialog for a Memo field will show a new property: 'Allow file upload'.

Note: If the optional Image Upload Feature Pack is installed, then the Field Properties dialog for a Memo field also shows the 'Allow image upload' property.

 

Image shows the Field Properties Dialog for an HTML Memo field if both the File Upload and Image Upload Feature Packs are Installed.

 

If 'Allow file upload' is enabled, then you must specify the folder where uploaded files are stored. You must enter a relative folder name here. The folder will be created in the webroot if it does not already exist.

If you allow image upload, then the toolbar will show a new button when you are editing the memo.

If you click the icon, the File Select window appears:

The wording and icons used in the window can be customized by clicking on the 'Image upload dialog customization' property smart field.

 

File selection window

Here is how the HTML memo field might  look after a file has been uploaded:

 

 

Pop-up Vs. In-line HTML Editor

If your HTML editor is for a field in the Detail View, then you have the option of showing the HTML editor 'in-line' or as a 'popup'.

If you enable the 'File upload' property, you should configure the HTML editor as a popup, and you should check the optional 'Has Click to edit' button. Otherwise, you will not be able to download the file by clicking on its hyperlink.