This How-To guide describes the steps required to configure your HTML form and FormMail to allow file uploads.
FormMail can email uploaded files to your or store them on your server.
Your HTML Form
Firstly, the HTTP protocol requires that you specify a particular encoding for the form submission. This encoding is specified in the HTML form tag with the enctype attribute.
<form method="post" action="http://your-site.com/formmail.php" name="SampleForm" enctype="multipart/form-data">
NOTE: HTML requires you to specify method="post" and enctype="multipart/form-data", as shown. Without these two attributes, file uploads will not work properly.
Next, you create form fields to specify file uploading. FormMail does not place a limit on the number of files you can upload.
<p>File to upload: <input type="file" name="first_file" /></p> <p>File to upload: <input type="file" name="second_file" /></p>
File uploading can represent a minor security problem for you. For example, an attacker could bypass your HTML form and use FormMail to send you many unwanted files. For this reason, the default for FormMail is to disallow file uploads.
To enable file uploads, look for the FILEUPLOADS setting in FormMail's configuration section and set it to "true", like this:
define("FILEUPLOADS",true); // set to true to allow file attachments
Most PHP installations allow file uploads by default. You may, however, need to contact your hosting provider and ask them to enable file uploads. The setting is in the server's php.ini file and is called upload_tmp_dir.
Limiting the File Upload Size
There is usually a maximum file size allowed for uploading files in PHP. This setting is also specified in the php.ini file and is called upload_max_filesize. The default is usually 2 megabytes. If you need a larger limit, you may need to contact your hosting provider.
On some servers, you can override this yourself in your own .htaccess file:
php_value upload_max_filesize "3M"
this will set the upload limit to 3 megabytes for a FormMail script located in the same directory as the .htaccess file.
If you want a smaller maximum size for file uploads, PHP supports a hidden field called MAX_FILE_SIZE:
<input type="hidden" name="MAX_FILE_SIZE" value="25000" />
In this example, PHP will limit the file uploads to 25,000 bytes. Note, however, this is easily bypassed by an attacker, so you shouldn't rely on it to protect you or your server.
Therefore, FormMail provides you with a secure way of limiting the size of uploaded files. In the configuration section look for MAX_FILE_UPLOAD_SIZE:
define("MAX_FILE_UPLOAD_SIZE",30); // default of 0 means that other software
FormMail interprets this setting in kilobytes. So, 30 means 30,720 bytes. If you set this value to zero, then FormMail does not enforce a limit on the uploaded file size (so any limit imposed will be by other systems as described above).
Very Large Files
If you need to allow users to upload very large files, there are several settings inside PHP that can affect this operation:
Your hosting provider controls these settings, but may provide a way for you to override them.
Using Conditions and Required
FormMail allows your HTML forms to control your user's file uploads using required and conditions. Review the How-To guide for these features for full details. Briefly, when you use the name of a file field in required, FormMail checks whether a file has been uploaded.
When you use the name of a file field in a conditions string comparison, FormMail substitutes the name of the file the user uploaded (the name of the file on the user's computer).
When used in a conditions numeric comparison, FormMail substitutes the size of the file in bytes.
Here's an example of checking that a file has been uploaded using required:
<input type="hidden" name="required" value="first_file:Please upload a file." />
This is the same example using conditions:
<input type="hidden" name="conditions1" value=":@ @TEST@first_file@Please upload a file.@" />
Here's an example of checking the file name provided the file has been uploaded (this example checks that the file ends in .pdf):
<input type="hidden" name="conditions1" value=":@ @IF@first_file@first_file~/^.*\.pdf$/i@@You can only upload PDFs@" />
Here's an example of checking the file size provided a file has been uploaded:
<input type="hidden" name="conditions1" value=":@ @IF@first_file@first_file#<10240@@Maximum file upload size is 10 kilobytes.@" />
This example checks that the file has been uploaded and checks the name of the file and its size:
<input type="hidden" name="conditions1" value=":@ @TEST@first_file@Please upload a file.@: @TEST@first_file~/^.*\.(pdf|jpg|jpeg|gif|png)$/i@You can only upload PDF or graphics files@: @TEST@first_file#<10240@Maximum file upload size is 10 kilobytes.@" />
Storing Uploaded Files on the Server
By default, FormMail attaches uploaded files to the email it sends you with the results of the form submission. You can, however, direct FormMail to store uploaded files on your server instead of emailing them to you.
To do this you need to create a directory or folder on your server. We call this the file repository. The file repository can be within or outside your web server document root. If you want to ensure the files are not downloadable from the web, we recommend you put the file repository outside (above) the document root.
The file repository must be writable by the web server software. In most cases this means you need to "chmod" the directory you create as mode 777 or rwxrwxrwx.
Once you've created the directory for the file repository, you need to know its full pathname. You then set this value in FormMail's configuration setting called $FILE_REPOSITORY:
$FILE_REPOSITORY = "/home/your-site/filerepos";
The actual directory or folder path will depend on your server.
Setting File Permission Modes
When an uploaded file is stored on your server you may want to control the permission modes. You can control the file permission modes with the FILE_MODE configuration setting in FormMail. Review the documentation above this setting in formmail.php for full details.
You can direct FormMail to rename the files that are uploaded. For example, your users will typically upload files with a variety of different names. In particular, you may want to indicate which field the file was uploaded in if your form allows multiple file uploads.
You rename files using the file_names hidden field. The syntax and features of this field are similar to deriving fields from other fields. In particular, the nextnum function will be important if you want to store files on your server.
This example prefixes the file name with a field identifying string:
<input type="hidden" name="file_names" value=" first_file=%'File1-'%.first_file, second_file=%'File2-'%.second_file" />
This example prefixes the file name with the date:
<input type="hidden" name="file_names" value="first_file=%date%.first_file" />
This example identifies the two files uploaded by the users who uploaded them:
<input type="hidden" name="file_names" value="first_file=realname.%'-file1'%, second_file=realname.%'-file2'%" />
The file_names feature does two things:
- Sets the name of the uploaded file for storage or email attachment.
- Creates (derives) a new field called "name_of_X", where X is the name of the file field. You can use this new field just like any other derived field. The above examples would create new fields called "name_of_first_file" and "name_of_second_file", whose values would be the new names for the files. Note however, the creation of the "name_of_" fields occurs after normal field derivations, so you cannot use these new fields in a derive_fields specification.
File renaming works with files stored on the server and also files attached to email.
Note that the original uploaded file name (the file on the form submitter's computer) is always available as the file name field.
So, "first_file" is the original file name and "name_of_first_file" is the new name of the file that you've chosen.
Rename But Keep File Extension
For download links and general application requirements, when you rename a file you will generally want to keep the original file extension or type.
For example, if the uploaded file is a JPEG, then you want to keep the ".jpg" extension.
To do this, you use the %ext% feature, which provides the file extension. However, it doesn't include the leading period, so you need to prepend that using %2E%.
<input type="hidden" name="file_names" value="first_file=realname.%'-file1'%.%2E%.%ext(first_file)%, second_file=realname.%'-file2'%.%2E%.%ext(second_file)%" />
Illegal Characters in File Names
It's important to remember that your users may use different operating systems with different rules for file names.
For example, a user might upload a file with a character that cannot be used in a file name when the file is stored on your server.
Therefore, you will generally need to use the file renaming features of FormMail as described above.
Working with Multi-Page Forms
To use file uploads with multi-page forms, you must set SCRATCH_PAD in FormMail's configuration section. This is required so that FormMail can save uploaded files in your private temporary folder when moving between the pages of your multi-page form.
Advanced Features for Multi-Page Forms
FormMail's multi-page features and file uploading can be used for very advanced and complex forms processing. Especially when combined with our FormMail Computation Module and Advanced Templates.
In these cases, you sometimes need to distinguish between files just uploaded from a page and files that were previously uploaded and saved to your file repository (see above).
Prior to version 8.13 of FormMail, the file field name would sometimes refer to a newly uploaded file and sometimes refer to the file previously stored in the repository. For very complex processing, this ambiguity was not helpful.
From version 8.13 of FormMail, the file field name on a submitted form now only refers to the file just uploaded (if any). Also, when a file is saved to the repository, FormMail creates a new field name that you can use to refer to the file so saved. The field name begins with the prefix "repository_". When the file is also renamed (see the renaming feature above), the new name of the file stored in the repository is a field with the prefix "repository_name_of_".
For example, suppose a page in your multi-page form sequence has a file upload field called "photo". On the next page (which will be a template page) and in email templates and other processing, you can refer to that uploaded file as "$photo", and, if renamed, its new name as "$name_of_photo".
If you've configured FormMail to save files to the repository, on subsequent pages your repository file can be referenced as "$repository_photo", and if it was renamed, "$name_of_repository_photo".