This article briefly describes important changes to the upload mechanism included in GeneXus 17 upgrade 4.
They are important because some of these changes affect the compatibility of the GeneXus code and interfaces of the generated solutions.
In GeneXus, the ways to upload a file to the server are as follows:
- In a Web Panel, using the ‘FileUpload’ User Control or another one that allows file uploads.
- In a Web Panel, using a Blob variable on the screen.
- In a Transaction, with an attribute of Blob, Multimedia type (Audio, Video, Image, BlobFile).
- In the Layout of a Work With for Smart Devices that is associated with a Transaction, and having an attribute of Blob, Multimedia type.
- A Procedure, Business Component, or API with REST interface that receives a parameter of Blob or Multimedia type (in a variable, attribute, or as an SDT field).
- In a Panel, by placing a Blob variable on the screen.
In general, this upload is automatically handled by GeneXus, especially when the client-side and server-side were developed in objects of the KB itself.
In other cases, as in point 4, which mentions the existing mechanism for integration with external systems, development of other User Controls, and so on, there is a mechanism documented in the wiki with the details.
Internally, for points 1, 4, 5, and 6 the file upload was done by calling the ‘/gxobject’ URL, and for points 2 and 3 a multipart POST is still done that is served by the object where the upload control is located.
Changes have been made to all upload mechanisms in order to improve security aspects. It is mainly an internal modification, but it affects compatibility in some scenarios, especially, but not exclusively, in point 5.
The new mechanism includes three main changes, as follows:
- To entry points invoked when uploading a file,
- To the physical file name once uploaded to the server,
- To the internal mechanism for handling the uploaded file.
They affect points 1, 4, 5, and 6 mentioned above.
At a conceptual level, the entry point is no longer generic for the entire webapp and is now one per object. In this way, the security aspects also become controlled by the object, like any of the other entry points that objects have.
More specifically, the service is no longer below ‘/gxobject’ and is now below ‘/<Object Name>/gxobject’, where ‘Object Name’ is the name by which the object is invoked via URL.
Example: If the URL is https://example.com/MyWebPanel.aspx, the service URL for the upload is https://example.com/MyWebPanel.aspx/gxobject.
Authentication and Authorization are also controlled by the GAM configuration of that object; and if authorization is not obtained, HTTP status code 403 is returned.
Those who need to maintain the previous, less secure mechanism, can apply what is documented here.
Note: For points 2 and 3, a multipart POST to a service associated with the object is still made as before, and the GAM configuration of the object itself is still taken as before. There are no changes in this regard.
The file that is physically uploaded to the server is given a GUID name and a tmp extension. In order not to lose data and to be able to handle it properly, a reference to the file is also stored, as well as the original file name and extension, in a cache with a key that is another GUID.
This cache reference is only valid for 10 minutes.
Two cases can be identified:
If the file was uploaded in an object other than a Transaction, the client side gets as a POST response the string gxupload:<GUID>; i.e. the reference to the uploaded file, as well as the name and extension of the originally uploaded file.
In a server-side event, that reference can be assigned to the Source property of a GeneXus File type variable. That variable of File type then points to the file, but when querying for its name and extension, the original ones are obtained (not the <GUID>.tmp) which allows, for example, validating if the file is of the expected type, as well as opening it, copying it or manipulating it in some way.
If the file was uploaded in a Transaction, what happens depends on whether the attribute is of Blob or Multimedia type. In addition, if it is a Blob it changes when the FileType Attribute and FileName Attribute properties are configured.
If it is an attribute of Blob type and the FileType Attribute and FileName Attribute properties are configured, the name and original extension of the file that was uploaded are stored in those attributes. Therefore, it is possible to control that they are a valid name and extension and in case they are not, an error can be displayed before saving the transaction.
If the record is saved, this file will be downloaded with the name and extension with which it was uploaded (adding a GUID in the middle to avoid name collision).
If it is a Blob type attribute and the FileType Attribute and FileName Attribute properties are not configured, the file is uploaded without keeping the original name and extension; also, when downloaded it will have a name with GUID and tmp extension.
If the attribute is of Multimedia type, before modifying the data, extension, and name of the uploaded file the user can check – by asking for the ImageType or ImageName properties of the attribute – if it is of Image type, and analogous properties exist for the Video, Audio, and BlobFile data types.
The internal changes mentioned above do not affect compatibility, except in these situations.
When other systems are used to upload files to a solution developed with GeneXus, the changes in the entry points mentioned above must be taken into account.
User controls that upload files to Web Panels must provide their own server-side mechanism to receive the files. The entry point for receiving files is only generated if there is a File Upload control in the layout.
After uploading a file, the File property of the variable pointing to the uploaded file (typically &FileUploadData) no longer returns the path to the file, but a reference to it.
If &Client is a Business Component, and ClientImage is a field of Image type, the following lines have no compatibility issues:
&Client.ClientImage = &FileUploadData.File
But, in the case that the uploaded file needs to be processed by an external program, the following is an example that may have issues:
The solution is to assign the reference to the uploaded file to an auxiliary variable of File data type:
&File.Source = &FileUploadData.File
Note: To get the original name and extension, you can read the fields FullName, Name or Extension of the &FileUploadData .