如何使用重命名过滤器(Zend_Form_Element File)中的逻辑来测试文件上传功能?

时间:2009-10-12 13:32:16

标签: php zend-framework file-upload zend-form

首先是我的代码:

class ProfileController extends Zend_Controller_Action {

private function getUploadAvatarForm()
{
    $form = new Zend_Form;
    $form->setAttrib('enctype', 'multipart/form-data');
    $form->setAction($this->view->baseUrl('/profile/upload-avatar'))
         ->setName('uploadAvatarForm')
         ->setMethod('POST');

    $element = new Zend_Form_Element_File('avatar');
    $element->setLabel('Upload an image:')
            ->addFilter('Rename',
                array('target' => '/path/toimages/directory/' . $this->userId . '.png',
                      'overwrite' => true)
            );

    $element->addValidator('Count', false, 1);
    $element->addValidator('Size', false, 102400);
    $element->addValidator('Extension', false, 'png');
    $form->addElement($element, 'avatar')
         ->addElement('submit', 'submit_upload', array('label' => 'upload'));
    return $form;
} 

public function uploadAvatarAction()
{
    $form = $this->getUploadAvatarForm();
    $this->view->form = $form;
    if (!$this->getRequest()->isPost() || !$form->isValid($_POST)) {
        return;
    }                
    if (!$form->avatar->receive()) {
        ... error...
    }
    ... ok ...
}

}

问题是:部分buissiness逻辑被置于重命名过滤器中。在我看来它值得,但可能是我错了。

我正在尝试测试它:

public function testUploadFile()
{
    $this->_doLogin('user', 'password');
    $this->getRequest()
         ->setMethod('POST'));
    $this->mockFileUpload();

    $this->dispatch('profile/upload-avatar');
    var_dump($this->getResponse()->getBody());
}

private function mockFileUpload()
{
    $_FILES = array(
        'avatar' => array(
            'name' => 'test.png',
            'type' => 'image/png',
            'tmp_name' => '/tmp/test.png',
            'error' => 0,
            'size' => 10127));
}

但得到了:

文件'avatar'被非法上传,可能是攻击

您能否建议我如何测试这种情况? (使用文件系统一切都会好的 - 我将使用vfsStream,所以问题只是模拟上传后的内容)

2 个答案:

答案 0 :(得分:0)

在您的测试类中,将表单设置为使用Zend_File_Transfer_Adapter_Http的扩展类并覆盖isValid()方法。您显然需要在ProfileController中将表单函数的范围更改为public。这将与PHPUnit一起使用。我还不确定如何将它与Zend_Test_PHPUnit_ControllerTestCase集成,但我需要在某个时候弄明白并更新。

$class = new ProfileController();
$form = $class->getUploadAvatarForm();
$form->getElement('avatar')->setTransferAdapter(new MockAdapter());

MockAdapter.php

class MockAdapter extends Zend_File_Transfer_Adapter_Http
{
    public function isValid($files = null)
    {
        return true;
    }
}

答案 1 :(得分:0)

我遇到了类似的问题。

经过一些代码阅读和实验后,我发现我的问题是由于我的表单的isValid函数调用两次(由次要代码故障引起)引起的。

在第二个isValid函数运行之前,不完全确定double isValid是如何导致我的tmp文件(上传的文件)被删除的,这使得Zend_Validate_File_Upload的第183行认为它不是一个正确的文件上传(因为它第二次寻找它已被删除):

如果你想检查你的临时文件是否由于某种原因而没有修改Zend_Validate_File_Upload的第183行:

case 0:
    var_dump(file_exists($content['tmp_name']));
    if (!is_uploaded_file($content['tmp_name'])) {
        $this->_throw($file, self::ATTACK);
    }
    break;

也许您的重命名过滤器正在移动或重命名文件?