Overview
Backends and collaborative applications often require users to upload media or data files. With a few lines of code, symfony handles all that needs to be taken care of - file renaming, move to upload directory, etc. And the users of the admin generator also have access to a new helper that reduces the implementation to a simple configuration.
Regular file upload
Uploading a file requires a form in a template, and an action to handle it. For the template, use the input_file_tag() helper in a form declared as multipart:
<?php echo form_tag('media/upload', 'multipart=true') ?> <?php echo input_file_tag('file') ?> <?php echo submit_tag('Send') ?> </form>
It generates the following HTML code:
<form method="post" enctype="multipart/form-data" action="media/upload"> <input type="file" name="file" id="file" value="" /> <input type="submit" name="commit" value="Send" /> </form>
The action (media/upload in this example) moves the file from the request to the upload directory:
public function executeUpload() { $fileName = $this->getRequest()->getFileName('file'); $this->getRequest()->moveFile('file', sfConfig::get('sf_upload_dir').'/'.$fileName); $this->redirect('media/show?filename='.$fileName); }
The sf_upload_dir parameter holds the absolute path, in your server, where the file is to be uploaded. For a project called myproject, it is usually /home/production/myproject/web/upload/. You can modify it easily in the config/config.php:
sfConfig::add(array( 'sf_upload_dir_name' => $sf_upload_dir_name = 'uploads', 'sf_upload_dir' => sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR.sfConfig::get('sf_web_dir_name').DIRECTORY_SEPARATOR.$sf_upload_dir_name, ));
note
Before moving the file from the request to the upload directory, you should sanitize the filename to replace special characters and avoid file system problems. In addition, you should escape the $fileName before passing it as a request parameter.
To display the uploaded file, use the sf_upload_dir_name parameter. For example, if the uploaded media is an image, the media/show template will display it with:
... <?php echo image_tag('/'.sfConfig::get('sf_upload_dir_name').'/'.$sf_params->get('filename')) ?>
Validation
Like regular form inputs, file upload tags can be validated by a symfony validator, the sfFileValidator. Just remember to put a custom file: true parameter in the validator declaration under the names key. For instance, the validate/upload.yml for the previous form should be written as follows:
methods:
post: [file]
names:
file:
required: Yes
required_msg: Please upload a file
validators: myFileValidator
file: true
myFileValidator:
class: sfFileValidator
param:
mime_types:
- 'image/jpeg'
- 'image/png'
- 'image/x-png'
- 'image/pjpeg'
mime_types_error: Only PNG and JPEG images are allowed
max_size: 512000
max_size_error: Max size is 512Kb
note
Due to inconsistencies between Internet Explorer and other browsers, you have to use the IE-specific mime types as well as the regular ones.
The sfFileValidator can validate the type of the uploaded file (you can specify an array of mime types) its size (you can specify a minimum and a maximum size).
Thumbnails
If you upload images, you might need to create thumbnails of each uploaded file. In this case, the sfThumbnail plugin might prove useful.
First, install the plugin using the symfony command line:
$ symfony plugin-install http://plugins.symfony-project.com/sfThumbnailPlugin $ symfony cc
note
If the GD library is not activated, you might have to uncomment the related line in your php.ini and restart your web server to enable PHP image handling functions.
Once the plugin is installed, you can use it through the sfThumbnail object. For instance, to save a thumbnail of maximum size 150x150px at the same time as the uploaded image in the above example, replace the media/upload action by:
public function executeUpload() { $fileName = $this->getRequest()->getFileName('file'); $thumbnail = new sfThumbnail(150, 150); $thumbnail->loadFile($this->getRequest()->getFilePath('file')); $thumbnail->save(sfConfig::get('sf_upload_dir').'/thumbnail/'.$fileName, 'image/png'); $this->getRequest()->moveFile('file', sfConfig::get('sf_upload_dir').'/'.$fileName); $this->redirect('media/show?filename='.$fileName); }
Don't forget to create the uploads/thumbnail/ directory before calling the action.
File upload with the admin generator
If your data model contains a field for a media, and if your administration is built using the admin generator, you can use the long named object_admin_input_file_tag() helper. It does everything for you with just a simple configuration.
For instance, if you have a User table with a photo column, the generator.yml for the edit view can be configured as follows:
edit:
title: User profile
fields:
photo:
name: User photo
help: max width 200px
type: admin_input_file_tag
upload_dir: pictures/users
params: include_link=pictures/users include_remove=true
display: [name, email, photo]
The upload_dir key sets the upload directory (under the uploads/ directory).
If you include an include_link param, a link will be added to the uploaded media (that is, if a media is uploaded). The text of the link is '[show file]' by default - unless you specify an include_text param.
If you include an include_remove param, the helper will display a link to allow easy removal of the media when clicked.
This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.