PeopleCode | Prompting the user to upload a file into the system
A. Native vs Enhanced
PeopleCode comes delivered with a number of functions for dealing with file attachments. Examples include ‘AddAttachment’, ‘ViewAttachment’, and ‘DeleteAttachment’. In addition, Oracle have created a library of attachment functions as part of the FILE_ATTACH_WRK record. These add some additional functionality and simplify the attachment process somewhat, even though the same native functions are used underneath.
The enhanced functions have almost identical names to their native counterparts. The native ‘AddAttachment’ function becomes ‘add_attachment’ in the function library. Also note that the enhanced attachment functions are stored in the ‘FieldChange’ event of the FILE_ATTACH_WRK record, not ‘FieldFormula’ as you’d normally expect for a function library (and no, I don’t know the reason for this either).
For further details of how the enhanced functions work, take a look at the functions themselves in the FILE_ATTACH_WRK record. The comments section of each function contains quite a bit of information on how to use the functions. For instance, there are a number of options in ‘add_attachment’ for setting the file name. You can get the system to change the file name by prepending the keys of the current record.
The code examples below cover the two approaches for uploading a file: using the native functions directly, and using the enhanced functions. As to which approach you should follow, this really gets down to personal preference. The native functions are fine for basic uploads, but if you are after some extra functionality, then the enhanced functions might better suit the requirement.
B. Storing the File
You will also need to decide what happens to the file after the user has clicked the ‘Upload’ button. You can either save the file to a location on the server, or you can store the file in a database record. I prefer to store the file immediately in a database record. This is the simpler option as it requires no knowledge of the underlying file structure, so the code will work equally as well whether run online or as part of a batch process. The file will also remain in the database for as long as you want (unless the DBAs decide that space is in an issue, in which case the file records are often the first ones targeted for purging).
The easiest way to set up a database record to store files is to insert the ‘FILE_ATTDET_SBR’ sub-record into a new record. In fact, you can create a record with just this one sub-record and no other fields (don’t forget to build the record as you normally would):
C. Using Native AddAttachment Function
Here’s an example of performing an upload via the native PeopleCode functions. This saves the uploaded file to the XX_FILE_TMP record:
/* Define file sub-record */ Local string &URL_ID = "record://XX_FILE_TMP"; /* Set max file size allowable – a value of 0 indicates no limit */ Local integer &InMaxSize = 0; /* Save the current page */ DoSaveNow(); /* Prompt the user for a text file */ &Result = AddAttachment(&URL_ID, &InOutAttachSysfilename, "", &InOutAttachUserfile, &InMaxSize); /* Check for file upload error */ If &Result <> %Attachment_Success then Error "Error in file upload: " | String(&Result); End-if;
D. Using Enhanced ‘add_attachment’ Function
Next is a similar example using the enhanced attachment functions.
Declare Function add_attachment PeopleCode FILE_ATTACH_WRK.ATTACHADD FieldChange; /* Define file sub-record */ Local string &URL_ID = "record://XX_FILE_TMP"; /* Upload to database record */ add_attachment(&URL_ID, "", "", 2, False, Null, &ATTACHSYSFILENAME, &ATTACHUSERFILE, 2, &Result);
E. Return Codes
In both these examples, the return code value from the function (&Result) can provide you with meaningful information if something goes wrong with the upload process. For instance, the return code of ‘6’ indicates that the maximum file size was exceeded. Check PeopleBooks if you’d like more information on what each code means. In the first example above, we have kept things simple by only referring to the ‘%Attachment_Success’ constant (value ‘0’). In the second example, we don’t need to do any error checking as the enhanced functions will do this for us, displaying an appropriate error depending on the return code.
F. Copying File to Server for Processing
Once your file has been uploaded using either approach, you can go ahead and copy the file to a temporary directory for processing (it’s not possible to read a file that’s only sitting in the database record). The following code can be added to the code snippets above:
/* The file will be copied to \uploads directory */ &file_name = &InOutAttachUserfile; &temp_dir = GetCwd() | "\uploads\"; /* Copy file from database record to the uploads directory */ &Result = GetAttachment(&URL_ID, &file_name, &temp_dir | &file_name); /* If the return code is any value other than 0, an error has occurred. */ If &Result <> 0 Then Exit; End-If; /* Open the file for reading */ &in_file = GetFile(&temp_dir | &file_name, "r", "a", %FilePath_Absolute); /* Process file here */
G. Deleting Attachments
Finally, it’s good practice to remove an attachment from the database once you no longer have any need of the file. To do this, use the ‘DeleteAttachment’ function:
/* Delete temp file */ &Result = DeleteAttachment(&URL_ID, &file_name);
Here’s the alternative ‘delete_attachment’ as per the enhanced functions:
Declare Function delete_attachment PeopleCode FILE_ATTACH_WRK.ATTACHDELETE FieldChange; /* Delete temp file */ delete_attachment(&URL_ID, &ATTACHSYSFILENAME, "", 2, &Result);
Note that these two ‘deletes’ only remove the file from the database record. If you wish to remove the file from a server directory, then refer to the related tips mentioned below.