March 18th, 2010 Category: Programacion Zend Framework
14 Comments »

Mi idea era subir un archivo dentro de un formulario, renombrar ese archivo con un id conseguido en esa misma operacion con el siguiente formato logo_{$id}.jpg . El problema es que cuando agregaba el setDestination del form me copiaba el archivo con su nombre original en la carpeta de destino. No conseguia renombrarlo.

Vi muchisimos ejemplos pero al parecer con la nueva version no andan ninguno, porque los que probe no me sirvieron de forma literal (es decir copy/paste ) .

Asi que tuve que ponerme a leer un poco :( . Despues de ver como funcionaba Zend_Form_Element_File. Trate de implementar la forma mas logica. La cual no me anduvo. Me acorde que cuando usas isValid de un Zend_Form, este ejecuta los filtros y las validaciones correspondientes. Pero encontre dentro de la documentacion la solucion a mi primer problema, el metodo setValueDisabled( true ) evita que se ejecute el filtro del elemento, asi puedo aplicar mi filtro para renombrar mi archivo despues de validarlo.

Mi segundo problema es que cuando implemente esto, no me guardaba el archivo en donde habia establecido. Para entender esto un poco Zend_Form_Element_File usa Zend_File_Tranfer que es el encargado de manipular el archivo. Lo que siguio fue traerme el adapter de Zend_File_Transfer de mi elemento, agregar los filtros y ejecutar el upload. Y listo tenia mi archivo subido ‘in the ZF way’.

Este es el formulario


class Application_Form_Company extends Zend_Form
{

    public function init()
    {

        $this->setAttrib('enctype', 'multipart/form-data');

        $this->addElement('text', 'name', array(
            'required'   => true,
            'validators' => array(
            ),
            'class' => 'sf'
        ));
        $this->addElement('file', 'logo', array(
            'class' => 'sf'
        ));
        $this->logo->addValidator( 'Extension', false, 'jpg,png,gif,jpeg' );
        $this->logo->addValidator( 'Size', false, '10024000' );
        $this->logo
            ->setDestination( APPLICATION_PATH . '/../public/empresas/imgs/' )
            ->setValueDisabled( true );

        $this->addElement('text', 'website', array(
            'required'   => true,
            'class' => 'sf'
        ));

        $this->addElement('text', 'telephone', array(
            'required'   => true,
            'class' => 'sf'
        ));

        $this->addElement('textarea', 'information', array(
            'required'   => true,
            'class' => 'sf'
        ));

        $this->setDecorators(
            array(
                array(
                    'ViewScript',
                    array( 'viewScript' => 'company/form.phtml' )
                )
            )
        );
    }
}

Asi quedo mi action

        ...
        $form = new Application_Form_Company();
        if ( $this->getRequest()->isPost() ) {
            $file = $form->logo;
            if( $form->isValid($this->getRequest()->getParams()) ) {
                $bind = $form->getValues();
                $company = new Application_Model_Company();

                if( $company->exists( $bind['name'] ) ) {
                    $form->name->addErrorMessage( "La empresa ya existe" );
                } else {
                    try {
                        $id = $company->save( $bind );
                    }catch( Exception $e ) {
                        $this->_helper->flashMessenger()
                            ->addMessage( 'Hubo un problema, revise los datos' );
                    }

                    // Traemos el adapter de Zend_File_Transfer
                    $upload = $form->logo->getTransferAdapter();

                    // Lo ideal es que el path lo trajeramos de un archivo de configuracion.
                    $upload->addFilter('Rename', array(
                        'target' => APPLICATION_PATH . '/../public/empresas/imgs/logo_'. $id .' .jpg',
                        'overwrite' => true
                    ));
                    var_dump( $upload->receive() );
                    ...

Invitame una Cerverza


Comentar


14 Responses

Diego 2010-03-25 18:07:25
Interesante. Creo que sería mas "robusto" mover el archivo dentro de try{} ya que puede queda inconsistente.

Pablo Morales 2010-04-12 17:59:12
Tenes Razon @Diego.

jorg-g 2010-05-05 16:14:32
hola pablo.. son principiante en zend.. me podrias ayudar con el upload pero sin utilizar zend_form.. tengo la vista pero ni idea de como lo haria en zend.. te agradeceria mucho tu ayuda..

Lautaro 2010-11-16 01:25:16
Hola pablo, sigo tus instrucciones pero no puedo renombrar el archivo cuando lo subo...este es mi form:
class Form_Cargapdf extends Zend_Form{

public function init(){

$this->setAttrib('enctype', 'multipart/form-data');

$obj= new Zend_Form_Element_Text('fecha');
$obj->setLabel('Fecha')
->setAttrib('maxLength', 10);
$this->addElement($obj);

$this->addElement('file', 'logo');
$this->logo->addValidator('Extension', false, 'pdf');

$this->logo
->setDestination('public/resource/edimpresa/pdf/')
->setValueDisabled(true);







/* $obj = new Zend_Form_Element_File('foto');
$obj->setLabel('Elija una foto para la portada:')
->setDestination('public/resource//edimpresa/pdf')
->addValidator('Size', true, '10MB')
->addValidator( 'Extension', true, 'jpg,png,gif,jpeg');
$this->addElement($obj);
*/

$obj= new Zend_Form_Element_Submit('submit');
$obj->setLabel('Subir');
$this->addElement($obj);

}
}

y este mi controller:
$form = new Form_Cargapdf();
$this->view->assign('form', $form);

if (!$this->_request->isPost()){
return;
}
/*if (!$form->getElement('foto')->receive()){
$this->view->assign('error_foto', true);
return;
}*/

if (!$form->getElement('logo')->receive()){
$this->view->assign('error_logo', true);
return;
}

if (!$form->isValid($this->_request->getPost())){
$form->reset();
$this->view->assign('form', $form);
return;
}
$id=date('l');
$fecha = $form->getElement('fecha')->getValue();
list($day,$mon,$year) = explode('-',$fecha);
$fecha = $year.'-'.$mon.'-'.$day;
//$foto = $form->foto->getValue();
$file = $form->logo;
// Traemos el adapter de Zend_File_Transfer
$upload = $form->logo->getTransferAdapter();
chmod('/public/resource/edimpresa/pdf/'.$file.'', 0777);
// Lo ideal es que el path lo trajeramos de un archivo de configuracion.
$upload->addFilter('Rename', array(
'target' => APPLICATION_PATH . '/../public/resource/edimpresa/pdf/logo_'.$id.'.pdf',
'overwrite' => true
));
var_dump($upload->receive());

el archivo se sube, pero con el nombre original...ya lo cambio mil veces, si tenes alguna solucion de lo agradecere!
saludos, lautaro!

Pablo Morales 2010-11-16 12:50:52
Hola Lautaro, decime tu version de Zend, por ahi hubo cambios.

Lautaro 2010-11-16 13:02:15
Hola Pablo, la version que uso es ZendFramework-1.9.8. De hecho en un momento logre que cambie el nombre, pero me dejo de funcionar el formulario. Yo uso ese form porque es el que aprendi, instancio las clases dentro del form, vi que vos no lo haces...pero probe de las 2 formas y no pude realizarlo...soy un poco estructurado, lo aprendi asi y no me sale de otra forma...Desde ya gracias.

Pablo Morales 2010-11-16 13:13:14
El que hace la magia es Zend_File_Transfer

Quise entrar en la pagina de Zend, pero no me anda, cuando vuelva te busco como hacerlo funcionar.

Pablo Morales 2010-11-16 13:36:52
Proba que en el rename solo poner la carpeta de destino, cuando hagas esto guarda el objeto en una variable, y despues hace esto.

$renameFilter->addFile( array('source' => $fileInfo['tmp_name'], 'target' => 'NUEVO ARCHIVO', 'overwrite' => true ) );

http://framework.zend.com/manual/en/zend.file.transfer.filters.html

Lautaro 2010-11-16 18:34:10
este es mi controlador, pero me dice que no use un objeto como array.
controlador:
$file = $form->logo;

// Traemos el adapter de Zend_File_Transfer
$upload = $form->logo->getTransferAdapter();

// Lo ideal es que el path lo trajeramos de un archivo de configuracion.
$upload->addFilter('Rename', array(
'target' => APPLICATION_PATH . '/../public/resource/edimpresa/pdf/',
'overwrite' => true
));
$upload->addFile( array('source' => $fileI['tmp_name'], 'target' => 'NUEVO ARCHIVO', 'overwrite' => true ) );
var_dump( $upload->receive() );


me tira este error...

Fatal error: Cannot use object of type Zend_Form_Element_File as array in /home/fl000021/public_html/application/controllers/AdminController.php on line 891, esa linea es
$upload->addFile( array('source' => $file['tmp_name'], 'target' => 'NUEVO ARCHIVO', 'overwrite' => true ) );

Voy a seguir probando, gracias por la ayuda hasta el momento!

Pablo Morales 2010-11-20 18:33:48
Lo estuve probando tal cual esta arriba y con la version 1.10.4 anda perfecto. Proba con esa version, por ahi cambio la implementacion.

Lautaro 2010-11-22 20:15:55
Gracias por responder, te hago una ultima consulta, yo ya tengo el sitio armado, para pasarme a la version 1.10.4, simplemente cambio las librerias? tendre algun problema con el resto del sitio?
Desde ya gracias.

Pablo Morales 2010-11-22 21:47:02
En teoria solo cambias la lib, y listo.

Pero deberias testear todo el sitio otra vez, por las dudas. Sino anda pones la lib anterior y listo.

fabian 2011-08-29 19:29:33
gracias por publicar estos ejemplos de zend .
como haria para guardar los archivos en una base de datos?
gracias..

fredy 2011-10-04 12:14:56
he estado leyendo tu tutorial y no me fue nada mal. quisiera hagas un aporte sobre datagrid con zend, que tenga un autocompletado por columna. me seria de mucha ayuda.