I've lost count of the number of times I've implemented an attachments page in
Visualforce, sometimes for a single file, sometimes for a finite number and once
or twice for an indeterminate number. Following the principles of
DRY, I decided
to create a custom component that would allow me to attach files to any
specified parent sobject with Add More functionality that allowed me to upload
several files at once. As its easy to forget what attachments you have
already uploaded, I also wanted the existing attachments to be listed. Below is
a screenshot of the completed component:
The component has a mandatory attribute named "sobjId" - this is the id of the
sobject that the uploaded files will be attached to. Note that you can't use the
name "id" for the attribute, as this is a standard attribute that allows the
component to be identified by other components in the page.
The Attachment sobjects backing the input file elements are stored in a list in
the controller that is initialised in the constructor to contain a single
element. Clicking the Add More button causes another five Attachment
sobjects to be appended to the list. As the user can choose to fill in the
attachments in any order (e.g. just populating the last two elements), we can't
simply insert the attachments when the save button is clicked, as that will
attempt to insert the empty attachments that the user hasn't supplied details
for. Thus we iterate the list and only insert those Attachments that have
the Body field populated.
Note that there is no field for the user to input the name of the Attachment -
I'm using the filename for the this, as the filename extension gives a browser a
good chance of automatically opening the attachment when it is downloaded.
The Done button simply takes the user back to the view page for the object
matching the supplied id attribute.
There's a couple of wrinkles when dealing with file uploads:
The code (including unit tests!) and Visualforce can be downloaded
here. Simply unzip into the src directory of your org in the Force.com
IDE.
Note that when using the example page, you'll need to supply the id of an
existing sobject (Account, Opportunity etc).