Uploading Files

It is quite common for a web application to allow users to upload files. It could be done to let the user provide his photo to be included in his profile on the forum, or to attach a project showing the problem to an issue description in Bug Tracker like application.

Morfik provides you with the tools required to handle file uploads on the server-side, and also gives you controls that can be used to provide the user interface for file uploading inside the browser.

Basic example

Let’s start from the basic example: using FileUploader to upload a file into a table.

First, you need to have a table to hold information about files being uploaded - a field of Picture or Document type is usually used for that purpose. Link the form where FileUploader widget is going to be used to that table. Note: make sure the table is not empty - FileUploader always works with the current record and will not add records by itself.

Now place FileUploader control on the form. Bring Properties panel up, find there DataField property and set it to point to the field that will contain the file uploaded by the user. That is all that has to be done - your users have ability to upload files now.

Linked and Embedded fields, URLRoot

When designing your table structure, you have a choice of making Document field either Linked or Embedded. This can be done by modifying field's Field Class.

Embedded means the file content will be stored inside database, while Linked means the contents of the uploaded file will be stored in a separate file and the database will only contain the link to that file (usually the name of the file).

If you use Linked fields, you can specify the folder where the files will be stored. This can be done by setting field's URLRoot in the Table Designer.

For example, if you want all files uploaded by the user to be placed into Uploads folder, just type in Uploads there. You can also specify nested subfolder in there, e.g. Documents\Uploads can be used.

OnUploadComplete

To get notified when the file has been successfully uploaded, you can handle OnUploadComplete event.

For example, if you let the user upload his photo, you may want to refresh the page once the new photo has been uploaded. To do so you can simply put RefreshPage call inside OnUploadComplete handler like this:

FX Code

Procedure Index.FileUploader1UploadComplete(Sender: TObject);
Begin
    RefreshPage(Nil);
End;

OnBeforeUploadFinalize

Sometimes you may need to do custom handling of files getting uploaded on the server-side. It could include some processing of the received file, or providing a custom storage implementation.

Since the user can send a file to the server at any time (and multiple users can submit files simultaneously), the server has to be able to handle it out of context of the form where FileUploader was used. That is why OnBeforeUploadFinalize is an event of TXApp, rather than of FileUploader itself.

Event handler has 3 parameters:


UploadData - This object contains all the information about the file being uploaded, including the file data itself.

UploadData.DataStream is a TMemoryStream instance which holds the file contents. You can use UploadData.DataStream.SaveToFile method to save the uploaded data to a file, or inspect the data using UploadData.DataStream.Memory and UploadData.DataStream.Size.

UploadData also provides the context information sent from the browser. This includes both system fields, such as uploaded file name and values added from the code using FileUploader.AddParam method. Here is the list of available system fields:

MFK$FILE_NAME - The name of the file being uploaded.

MFK$CTRL_NAME - The name of FileUploader control that was used to upload the file.

MFK$FORM_NAME - The name of the form containing the FileUploader

MFK$TABLE_NAME - The name of the table to which FileUploader is bound. (this field can be empty if FileUploader is not data-bound).

MFK$FIELD_NAME - The value of DataField property of FileUploader

MFK$KEY_FIELD_NAME and MFK$KEY_FIELD_VALUE - the name and the value of the key field that can be used to locate the record which should be used to receive the uploaded file.


Response – An instance of THTTPResponse class. Can be used to send the result of the processing back to the user, mostly used internally by the framework.


DoProceed – Indicates if the default processing should take place. If you implement custom storage, or want to cancel the upload, set this parameter to False.


Here's a sample code which simply saves all files to the same folder where xApp is located:

FX Code

Procedure Project13XApp.XAppBeforeUploadFinalize(UploadData: TUploadData; Response: THTTPResponse; Var DoProceed: Boolean);
Begin
    UploadData.DataStream.SaveToFile(UploadData['MFK$FILE_NAME']);
    DoProceed := False;
End;

Maximum File Size Limit

To prevent the user from accidentally uploading large files the limit on the maximum allowed file size is used. Any attempt to upload a file which size exceed the limit will be denied.

By default, the value is set to be 1MB. If you need to adjust it, you can use Catalog.PostLimits. The code below sets the limit to be 4MB (note, the value provided is in bytes):

FX Code

    Catalog.PostLimits.AddLimit('fileupload', 4 * 1024 * 1024);


Note: if you are using IIS 7, the maximum file size will be limited to ~28MB. For the instructions on how to overcome that limit, please refer to this [Microsoft KB article]

S3 uploader

[Amazon S3] provides a service that allows you to store and retrieve any amount of data, at any time, from anywhere on the web.

In some cases you may consider using S3 as storage for the files uploaded by your users. In that case you might find S3 File Uploader package useful. Please refer to Amazon S3 File Uploader article for a detailed description of how to use that package.

Back to top