Tuesday, March 8, 2011

What if Zend_File_Transfer_Adapter_Http receive() returns false?

I wasn't able to locale comprehensive information about Zend_File_Transfer_Adapter_Http in Zend Framework documentation during couple hours of debug and digging into Google results. So when I've finally figured out everything then decided to share my experience with others and also have a little note for my self about the architecture of this component.

What to do if code example from documentation doesn't works and doesn't throws any exceptions.

So, the problem was with the following code that is almost copy/pasted from official documentation:

$upload = new Zend_File_Transfer_Adapter_Http();
$upload->addFilter('Rename', array('target' => '/path-to-file/' . $filename));
try {
    // upload the file
    $upload->receive();
} catch (Zend_File_Transfer_Exception $e) {
    $e->getMessage();
}

For some reason this code wasn't working for me, BUT more serious problem was that it doesn't throws any catchable exception to indicate that some error occurred.

During debug session and searching on Google, I've found that method receive() returns a boolean value that indicates whether the files processing was successful or not.
And finally I was able to locale the method getMessages() that returns the list of issues. The final working code was:

$upload = new Zend_File_Transfer_Adapter_Http();
$upload->addFilter('Rename', array('target' => '/path-to-file/' . $filename));
try {
    // upload the file
    $res = $upload->receive();
  
    if ($res === false) {
        $messages = $upload->getMessages();
        $form->addError($messages);
        // invalidate the form and display errors to user
        // ...

    } else {
        // all files were successfully uploaded
        // write data to database and redirect to success page
        // ...

    }

} catch (Zend_File_Transfer_Exception $e) {
    // some kind of serious problems occured
    $e->getMessage();
}

It looks ugly for the first time, because it has couple levels of errors processing for the same method receive().

The alternative solution can be like:

$upload = new Zend_File_Transfer_Adapter_Http();
$upload->addFilter('Rename', array('target' => '/path-to-file/' . $filename));


if (!$upload->isValid()) {
        $messages = $upload->getMessages();
        $form->addError($messages);
        // invalidate the form and display errors to user
        // ...
}


try {
    // upload the file
    $upload->receive();

    // all files were successfully uploaded
    // write data to database and redirect to success page
    // ...

} catch (Zend_File_Transfer_Exception $e) {
    // some kind of serious problems occured
    $e->getMessage();
}

From the technical point of view everything can be very simple and clear. We actually have 2 levels of errors processing here:

1. Errors that can be corrected by user.

Uploaded data errors that are presented to user on form validation and can be corrected by user, for example the file size is too large or file format is incorrect.

2. Errors that can't be corrected by end user.

Critical system errors that are not resolvable by user and here is where exception comes to, shows error controller and application fail message, for example no writeable permissions for destination directory.

Hope this material will help someone to avoid misunderstanding with this component too.