{"id":26,"date":"2013-10-02T20:34:46","date_gmt":"2013-10-02T23:34:46","guid":{"rendered":"http:\/\/arielnavarrete.wordpress.com\/?p=26"},"modified":"2013-10-02T20:34:46","modified_gmt":"2013-10-02T23:34:46","slug":"subir-imagenes-sin-habilitar-la-extension-php_infofile","status":"publish","type":"post","link":"https:\/\/arielnavarrete.cl\/blog\/2013\/10\/02\/subir-imagenes-sin-habilitar-la-extension-php_infofile\/","title":{"rendered":"Subir imagenes sin habilitar la extension php_fileinfo"},"content":{"rendered":"<p>Estoy trabajando en un proyecto hecho en Symfony2, un framework muy util y que simplifica mucho las cosas, me toco justamente el tema de subir una imagen al servidor.<\/p>\n<p><!--more Seguir leyendo...--><br \/>\nPara ello ocupe un Bundle llamado <a title=\"VichUploaderBundle\" href=\"https:\/\/github.com\/dustin10\/VichUploaderBundle\" target=\"_blank\">VichUploader<\/a>, el cual permite y facilita mucho el tema de subir imagenes, segui la configuracion\u00a0 basica que requeria y finalmente mi config,yml quedo asi<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\nvich_uploader:\n    db_driver: orm\n    gaufrette: true\n    storage: vich_uploader.storage.gaufrette\n    mappings:\n       product_image:\n            uri_prefix: \/images\/update\n            upload_destination: product_image_fs\n            namer: vich_uploader.namer_uniqid\n            delete_on_remove: true #El archivo debe ser eliminado del sistema de archivos cuando se quita la entidad\n            delete_on_update: true #el archivo debe ser eliminado del sistema de archivos cuando el archivo se sustituye por otra\n<\/pre>\n<p>Una vez funcionando sin errores, hice la respectiva prueba de subir una imagen, en este momento me aparecio un lindo error<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)<\/pre>\n<p>La solucion a esto es en teoria muy sencilla, solo deberiamos habilitar la extension \u00abphp_infofile\u00bb y listo<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">extension=php_fileinfo.dll<\/pre>\n<p>Pero&#8230; que sucede si tenemos nuestra pagina web alojada en un Hosting que NO tiene habilitada esta extension? pues tenemos dos soluciones<\/p>\n<ol>\n<li>buscamos otro hosting<\/li>\n<li>Intentamos otra manera de subir una imagen<\/li>\n<\/ol>\n<p>En mi caso tuve que ocupar la segunda opcion \ud83d\ude41\u00a0 y aqui fue donde vino una linda odisea que por lo menos logre encontrar una solucion<\/p>\n<p>Primero quitaremos la validacion existente en nuestra entidad para las extensiones mimes<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\nmimeTypes = {&amp;quot;image\/jpg&amp;quot;, &amp;quot;image\/jpeg&amp;quot;, &amp;quot;image\/png&amp;quot;},\n<\/pre>\n<p>Debido a que lo reemplazaremos por una validacion con Constraint, por lo tanto nos quedaria asi<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">use AN\\PortalBundle\\Validator\\Constraints as ANAssert;\n\nclass ArchivosCandidato\n{\n   \/**\n     * @Assert\\File(\n     *     maxSize=&amp;quot;3M&amp;quot;\n     * )\n     * @Vich\\UploadableField(mapping=&amp;quot;product_image&amp;quot;, fileNameProperty=&amp;quot;imageName&amp;quot;)\n     *\n     * @var File $image\n     * @ANAssert\\ContainsMimeType\n     *\/\n    protected $file;\n\n   \/\/...\n}<\/pre>\n<p>Notese que solo estamos validando el tama\u00f1o del archivo y mediante el \u00abContainsMimeType\u00bb, validaremos la extension<\/p>\n<p>Creamos nuestro archivo \u00abContainsMimeType.php\u00bb<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">namespace AN\\PortalBundle\\Validator\\Constraints;\n\nuse Symfony\\Component\\Validator\\Constraint;\n\n\/**\n * @Annotation\n *\/\nclass ContainsMimeType extends Constraint\n{\n    public $message = &#039;errores.ContainsMimeType&#039;;\n}<\/pre>\n<p>Creamos nuestro archivo \u00abContainsMimeTypeValidator.php\u00bb el cual contendra la logica y las extensiones permitidas, esto lo puedes pasar a un parametro en tu archivo de configuracion, pero eso lo vera cada uno<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">namespace AN\\PortalBundle\\Validator\\Constraints;\n\nuse Symfony\\Component\\Validator\\Constraint;\nuse Symfony\\Component\\Validator\\ConstraintValidator;\n\nclass ContainsMimeTypeValidator extends ConstraintValidator\n{\n    public function validate($file, Constraint $constraint)\n    {\n        \/\/Default\n        $return = false;\n\n        \/\/Tipos permitidos\n        $listType = &amp;quot;image\/png,image\/jpeg,image\/pjpeg&amp;quot;;\n\n        try\n        {\n            \/\/Tipo actual\n            $type = $file-&amp;gt;getClientMimeType();\n\n            \/\/Si esta dentro del listado, seteamos true para que no muestra una excepcion\n            if(substr_count($listType, $type) &amp;gt; 0)\n                $return = true;\n        }\n        catch(\\Exception $e)\n        {}\n\n        \/\/Definimos si mostramos o no el mensaje de error o excepcion\n        if($return == false)\n        {\n             $this-&amp;gt;context-&amp;gt;addViolation($constraint-&amp;gt;message, array(\n                    &#039;{{ types }}&#039;   =&amp;gt; &#039;&amp;quot;&#039;.$listType .&#039;&amp;quot;&#039;,\n                ));\n        }\n    }\n}<\/pre>\n<p>La idea es bastante simple, setea una variable de retorno, y si no encuentra la extension u ocurre algun error agrega un constraint con el error<\/p>\n<p>Con esto ya estariamos validando la extension de nuestro archivo, pero si estamos ocupando \u00abvich\u00bb seguiriamos teniendo problemas, esto debido a que si ocupamos<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">namer: vich_uploader.namer_uniqid<\/pre>\n<p>Esta funcion aun sigue ocupando \u00abphp_fileinfo\u00bb, por lo tanto tenemos dos soluciones:<\/p>\n<ul>\n<li>Ocupar \u00abvich_uploader.namer_origname\u00bb<\/li>\n<li>Clonar o crear nuestro propio \u00abvich_uploader.namer_uniqid\u00bb<\/li>\n<\/ul>\n<p>Yo queria seguir teniendo un ID unico por cada imagen, asi que ocupe la segunda solucion propuesta, y clone el \u00abvich_uploader.namer_uniqid\u00bb, si tu optas por la primera opcion, lo que sigue a continuacion no deberas tomarlo en cuenta.<\/p>\n<p><strong>Clonando \u00abvich_uploader.namer_uniqid\u00bb<\/strong><\/p>\n<p>En mi caso tengo las rutas en parameters.yml para cambiarlos mas facilmente<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">#Crea nombre unico para archivos con VICH\ngestor_vich_namer_uniqid.class: AN\\PortalBundle\\Services\\Naming\\UniqidNamer<\/pre>\n<p>En nuestro archivo \u00abservices.yml\u00bb<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">#Creamos un Servicio que creara un nombre Unico para subir archivos con VICH\nan.gestor.vichnameruniqid:\n    class: &amp;quot;%gestor_vich_namer_uniqid.class%&amp;quot;<\/pre>\n<p>En config.yml indicamos que estamos llamando a un nuevo namer<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">vich_uploader:\n    db_driver: orm\n    gaufrette: true\n    storage: vich_uploader.storage.gaufrette\n    mappings:\n        product_image:\n            uri_prefix: %vich_url_images%%locale%\n            upload_destination: product_image_fs\n            namer: an.gestor.vichnameruniqid<\/pre>\n<p>Nosete que aqui solo cambia el \u00abnamer:\u00bb lo demas sigue tal cual lo tienes<\/p>\n<p>Por ultimo, creamos nuestro archivo \u00abUniqidNamer.php\u00bb (ocupe el mismo nombre porque es casi lo mismo)<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">namespace AN\\PortalBundle\\Services\\Naming;\nuse Vich\\UploaderBundle\\Naming\\NamerInterface;\n\n\/**\n * UniqidNamer\n *\n *\/\nclass UniqidNamer implements NamerInterface\n{\n    \/**\n     * {@inheritDoc}\n     *\/\n    public function name($obj, $field)\n    {\n        $refObj = new \\ReflectionObject($obj);\n\n        $refProp = $refObj-&amp;gt;getProperty($field);\n        $refProp-&amp;gt;setAccessible(true);\n\n        $file = $refProp-&amp;gt;getValue($obj);\n\n        $name = uniqid();\n\n        \/\/Seteamos la extension\n        $extension = strtolower($file-&amp;gt;getClientOriginalExtension());\n\n        if (strlen($extension) &amp;gt; 0) {\n            $name = sprintf(&#039;%s.%s&#039;, $name, $extension);\n        }\n\n        return $name;\n    }\n}<\/pre>\n<p>Aqui lo unico diferente en comparacion con el archivo original es en la forma de obtener la extension, como ya validamos con nuestro Constraint que la extension fuera correcta, aqui solo ocupamos la extension original<\/p>\n<p>Eso seria todo, si es que no se me olvido nada<\/p>\n<p>El post oficial en donde deje esto fue <a href=\"http:\/\/stackoverflow.com\/questions\/18710240\/upload-images-without-the-extension-php-infofile-with-symfony2-and-vich\" target=\"_blank\">aqui<\/a><\/p>\n<p>Atte, Ariel<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Estoy trabajando en un proyecto hecho en Symfony2, un framework muy util y que simplifica mucho las cosas, me toco justamente el tema de subir una imagen al servidor.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8,12,14],"tags":[23,25],"class_list":["post-26","post","type-post","status-publish","format-standard","hentry","category-php-2","category-symfony2-2","category-vichuploaderbundle","tag-php","tag-symfony2"],"_links":{"self":[{"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/posts\/26","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/comments?post=26"}],"version-history":[{"count":0,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/posts\/26\/revisions"}],"wp:attachment":[{"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/media?parent=26"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/categories?post=26"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/arielnavarrete.cl\/blog\/wp-json\/wp\/v2\/tags?post=26"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}