Caution: You are browsing the legacy 1.x part of this website.
This version of symfony is not maintained anymore. If some of your projects still use this version, consider upgrading.
This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.

Master Symfony2 fundamentals

Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).
trainings.sensiolabs.com

Discover the SensioLabs Support

Access to the SensioLabs Competency Center for an exclusive and tailor-made support on Symfony
sensiolabs.com
Blackfire Profiler Fire up your PHP Apps Performance

PHP Project Quality Done Right

How to upload a file

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.