Managing File Uploads with the Zend Framework

by Jason Gilmore

Creating the next great community-driven Website? Using the Zend Framework, you can validate and manage your users' file uploads with ease. Read on to learn how.


Whether managing videos to YouTube, sharing PowerPoint presentations on SlideShare, or using the open source e-commerce platform Magento to update your online store's product images, chances are you've become well acquainted with the Web-based mechanism used to upload files to the Web. But how does this mechanism actually work? What process results in the file being transferred from your computer to the remote server? In this tutorial I'll show you how to create your own file upload mechanism using the popular Zend Framework, which makes accepting, validating, and processing uploaded files a walk in the park.

Configuring PHP to Handle File Uploads

PHP is natively capable of performing the task of managing file uploads submitted via a Web form, however whether you're using standard PHP code or the Zend Framework to manage your uploads, you'll probably want to take a moment to examine several of the configuration directives which directly impact PHP's capability to do so:

  • file_uploads: This directive enables PHP's file upload capabilities. By default this directive is enabled.
  • upload_max_filesize: This directive defines the maximum allowable size of an uploaded file. By default this directive is set to 2 Megabytes.
  • upload_tmp_dir: This directive defines the temporary directory used by PHP to store uploaded files before they are moved to their final destination as determined by the developer. By default this directive is not assigned a value, meaning PHP will use the system's default (for instance, /tmp on many Linux distributions)
  • post_max_size:
  • max_execution_time: Although not strictly related to file uploads, this directive nonethless plays an important role in PHP's file upload capabilities because it defines the amount of time a PHP script will execute. Because particularly large files may require significant periods of time to transfer to the file server, you might consider increasing this directive's default of 30 seconds to 60 or even 90 seconds.

Creating a File Upload Form

With PHP properly tuned to handle your specific file upload requirements, let's create an example Web form, capable of browsing your local computer's file system and identifying a file for upload. We'll keep things simple, creating the file upload form presented in Figure 1.

Figure 1. A simple file upload form

Creating this form is almost identical to other forms you've created in the past, with a few slight yet important changes. The HTML used to create this form is presented in Listing 1. As is typical with the Zend Framework, I've placed this form in a view named upload.phtml, which forms part of an action named upload located in a controller named admin.

  <form enctype="multipart/form-data" method="post" action="/admin/upload">
      What file would you like to upload?<br />
      <input type="file" name="video-upload" size="40" />
      <input type="submit" name="submit" class="submit" value="Upload Video" />

Listing 1. The file upload form HTML

In particular you should take note of two important bits of code found in this form:

  • enctype="multipart/form-data": This form attribute should be used when you send large amounts of binary data via a Web form. Because files such as spreadsheets and videos do indeed contain large amounts of binary data, be sure to include this attribute when creating a file upload form.
  • <input type="file" name="video-upload" size="40" />: This form element will create the form mechanism allowing users to search their local file system for a file they wish to upload. When the submit button is pressed, this file will be uploaded and sent to the script as identified by the form action (in this case, upload.php) for further processing.

As the second bullet point states, the file will be uploaded to the script identified by the form's action attribute. However unless the script actually does something with the file, the data will be lost. In the next section you'll learn how to use the Zend Framework's Zend_File_Transfer component to process this uploaded file.

Introducing the Zend_File_Transfer Component

Like so many of the other powerful components made available through the Zend Framework, the Zend_File_Transfer component is intended to make your life much easier when it comes to the task of uploading files from a user's computer to a Web server. In actuality, this component is much more flexible than merely handling uploads; it can also be used to transfer files using protocols such as FTP and WebDAV, however for the purposes of this tutorial we'll stick to its initially stated purpose. Let's begin by creating the simplest process possible in the upload action which is nonetheless capable of accepting and processing an uploaded file:

  01 public function uploadAction()
  02 {
  04   if ($this->getRequest()->isPost()) {
  06     $upload = new Zend_File_Transfer_Adapter_Http();
  08     $upload->setDestination($this->config->uploads->product->supplements);
  10     if ($upload->receive()) { 
  11       echo "The file has been uploaded!";
  12     }
  14   }
  16 }

I've added line numbers to the action, so the important bits of the code can be easily referenced in the summary that follows:

  • Line 04 determines whether a POST request has been submitted to the action. This is useful for creating actions which are responsible for both presenting the form to the user, and acting upon any data submitted through the form.
  • Line 06 invokes the Zend_File_Transfer class component, using specifically the HTTP adapter which is capable of processing data submitted through a Web form.
  • Line 08 sets the final destination of the uploaded file. While you're free to pass a path directly into this method, I find it far more convenient to store the path in the application.ini file, and then retrieve the configuration parameter as needed. This allows me to easily change that path destination as desired, a convenience which is particularly appreciated when moving code from my development to production servers.
  • Line 10 is responsible for accepting the file and moving it to the desired destination.

Believe it or not, these sixteen lines are capable of accepting and moving an uploaded file to the desired location on your server! However, at this point your alarm bells should be sounding off, because the script is missing a crucial step which should be part of any process involved in accepting user input. That's right, this script allows the user to upload any file he pleases, which is almost certainly a recipe for disaster! Thankfully, the Zend_File_Transfer component is packed with data validation methods capable of examining practically every conceivable aspect of the file upload process.

Validating Your File Uploads

At the most basic level, you'll probably want to examine one or several key characteristics of the file being uploaded, including the file's size or MIME type. Several methods are available for retrieving these characteristics. For instance, to retrieve the file's MIME type, call getMimeType() after receiving the file:

  if ($upload->receive()) {
    echo "The file type is {$upload->getMimeType()}"; 

For instance, if you uploaded a PDF to the server and called the getMimeType method, it would return application/x-pdf. This can be quite useful when the user should be restricted to uploading files of a certain type. Here's an example:

  if ($upload->getMimeType() == "application/x-pdf") {
    echo "File received";
  } else {
    echo "Please upload a PDF";

Of course, examining the file size or type is only a small part of the validation process. To facilitate the many verifications you'll likely want to carry out before accepting an uploaded file, the Zend_File_Transfer component offers 18 validation methods. You can view a complete list of these validators by navigating to the appropriate section of the Zend Framework documentation. One of my favorite available validators is ImageSize, which will examine an uploaded image's dimensions, ensuring they fall within a preset minimum and maximum range. This can be very useful for situations in which you wanted to for instance give usrs the opportunity to upload an avatar thumbnail, but want to keep the thumbnails uniform. This example will ensure all uploaded images are of type PNG, and further, conform to a size of 160 by 160 pixels:

  if ($this->getRequest()->isPost()) {
    $upload = new Zend_File_Transfer_Adapter_Http();
    $upload->addValidator('MimeType', false, 'image/png');
    $upload->addValidator('ImageSize', false,
      array('minwidth' => 160,
        'maxwidth' => 160,
        'minheight' => 160,
        'maxheight' => 160)
    if ($upload->isValid()) {
      echo "File received";
    } else {
      echo "Please upload a file of type PNG and dimensions 160x160 pixels.";

Where to From Here?

With user-driven content of all formats now a crucial part of the Web, your project's success may depend upon just how efficiently that data can be transferred from the user to your Web server. The Zend Framework's Zend_File_Transfer component goes a long way towards reducing the amount of complexity and tedium involved in offering such features to your users!

About the Author

Jason Gilmore is founder of EasyPHPWebsites.com, and author of the popular book, "Easy PHP Websites with the Zend Framework". Formerly Apress' open source editor, Jason fostered the development of more than 60 books, along the way helping to transform their open source line into one of the industry’s most respected publishing programs. Over the years he's authored several other books, including the best-selling Beginning PHP and MySQL: From Novice to Professional (currently in its third edition), Beginning PHP and PostgreSQL: From Novice to Professional, and Beginning PHP and Oracle: From Novice to Professional.

Jason is a cofounder and speaker chair of CodeMash, a nonprofit organization tasked with hosting an annual namesake developer’s conference, and was a member of the 2008 MySQL Conference speaker selection board.

Jason has published more than 100 tutorials and articles within prominent publications such as Developer.com, Linux Magazine, and TechTarget.

This article was originally published on Friday Nov 6th 2009
Mobile Site | Full Site