{"id":229884,"date":"2022-11-22T17:21:00","date_gmt":"2022-11-22T14:21:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=229884"},"modified":"2022-11-22T20:34:37","modified_gmt":"2022-11-22T17:34:37","slug":"carga-de-archivos-en-wordpress-revisited-parte-2-el-lado-del-servidor","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/carga-de-archivos-en-wordpress-revisited-parte-2-el-lado-del-servidor\/","title":{"rendered":"Carga de archivos en WordPress Revisited, Parte 2 &#8211; El lado del servidor"},"content":{"rendered":"\n<p>Antes de saltar directamente al c\u00f3digo para esto, quer\u00eda mencionar dos cosas:<\/p>\n<ol>\n<li>S\u00ed, he cubierto esto con cierto detalle hace <strong><a href=\"https:\/\/tommcfarlin.com\/uploading-files-to-a-custom-directory\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">un tiempo,<\/a><\/strong><\/li>\n<li>Y esta es la segunda parte de una serie de dos partes.<\/li>\n<\/ol>\n<p>Si no has le\u00eddo <a href=\"https:\/\/wordpress.mediadoma.com\/es\/subir-archivos-en-wordpress-revisado-parte-1-el-lado-del-cliente\/\" title=\"la primera parte\">la primera parte<\/a>, hazlo primero. La idea es que el c\u00f3digo funcione junto con lo que voy a cubrir en esta publicaci\u00f3n para asegurarme de que tanto el lado del cliente como el lado del servidor est\u00e9n cubiertos.<\/p>\n<p>En \u00faltima instancia, la raz\u00f3n para desglosarlo de esta manera no es solo para asegurarse de que las cosas se hagan correctamente, sino tambi\u00e9n para asegurarse de que el usuario tenga la experiencia m\u00e1s positiva posible.<\/p>\n<p>Dicho esto, aqu\u00ed se explica c\u00f3mo cargar archivos en WordPress en el lado del servidor.<\/p>\n<h2>Subir archivos en WordPress en el lado del servidor<\/h2>\n<p>Tenga en cuenta que, aunque hay algunas comprobaciones de seguridad que pueden y deben realizarse, todav\u00eda tengo que encontrar una manera que sea completamente infalible para detectar que el archivo que se est\u00e1 cargando es del tipo adecuado.<\/p>\n<p>Eso significa que todav\u00eda existe la posibilidad de que se cargue un tipo de archivo incorrecto. Si esto es malicioso o no, obviamente depende del usuario final. Solo comparto esto para que quede claro que el c\u00f3digo que voy a mostrar es tan bueno como puedo proporcionar, pero que todav\u00eda hay un nivel de discreci\u00f3n que debe usar.<\/p>\n<p>Quiz\u00e1s valga la pena incluso buscar una biblioteca de terceros para validar los datos binarios una vez que se reciben. Pero yo divago.<\/p>\n<h3>1 Verificar permisos de usuario<\/h3>\n<p>Recuerde que cada vez que creamos el front-end, hacemos que WordPress genere un nonce para que podamos usarlo para asegurarnos de que el usuario tiene permiso para cargar el archivo.<\/p>\n<p>Adem\u00e1s de verificar el nonce, hay varias otras cosas que me gusta verificar, todas las cuales est\u00e1n envueltas en un m\u00e9todo llamado <strong>userCanSave<\/strong>.<\/p>\n<p>Primero, <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-00-nonce-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">recuerda el front-end:<\/a><\/strong><\/p>\n<pre><code>&lt;form method=\"post\"\n      enctype=\"multipart\/form-data\"\n      action=\"&lt;?php echo esc_html(admin_url('admin-post.php')); ?&gt;\"\"&gt;\n    &lt;!-- Snip For Brevity ---&gt;\n    &lt;?php\n    wp_nonce_field(\n        'acme-item-upload',\n        'acme-item-importer'\n    );\n    ?&gt;\n&lt;\/form&gt;<\/code><\/pre>\n<p>Luego mira c\u00f3mo lo uso en el c\u00f3digo. Primero, defino la <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-01-usercansave-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">funci\u00f3n<\/a><\/strong> <strong>userCanSave<a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-01-usercansave-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external\"><\/a><\/strong> :<\/p>\n<pre><code>&lt;?php\n\n\/**\n * Determines if the current user has permission to upload a file based on their current role and the values\n * of the security nonce.\n *\n * @param  string $nonce     The WordPress-generated nonce.\n * @param  string $action    The developer-generated action name.\n * @return bool              True if the user has permission to save; otherwise, false.\n *\/\nprivate function userCanSave($nonce, $action)\n{\n    $isNonceSet   = isset($_POST[$nonce]);\n    $isValidNonce = false;\n\n    if ($isNonceSet) {\n        $isValidNonce = wp_verify_nonce($_POST[$nonce], $action);\n    }\n\n    return ($isNonceSet &amp;&amp; $isValidNonce);\n}\n<\/code><\/pre>\n<p>Y luego simplemente llamo a esto al comienzo del proceso. Si falla, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-01-save-part1-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">vuelvo<\/a>.<\/p>\n<pre><code>&lt;?php\n\n\/**\n * Assuming the user has permission, verifies the security nonce and uploads the PDF file to the `uploads`\n * directory and the Media Library.\n *\/\npublic function save()\n{\n  if (!$this-&gt;userCanSave('acme-item-importer', 'acme-item-upload')) {\n    return;\n  }\n\n  \/\/ More to come...\n\n}\n<\/code><\/pre>\n<p>Recomiendo mostrar un mensaje de error, pero estoy divagando en este punto ya que hay algunas formas de hacer esto dentro de la publicaci\u00f3n.<\/p>\n<h3>2 Sube el archivo<\/h3>\n<p>Suponiendo que el usuario tiene permiso para verificar el archivo, entonces es seguro cargar el archivo. El proceso para hacer esto es sencillo pero a\u00fan requiere un poco de trabajo con la API de WordPress (es decir, con la funci\u00f3n <a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/wp_upload_bits\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_upload_bits<\/a> ).<\/p>\n<p>Primero, el archivo debe tomarse de <a href=\"https:\/\/php.net\/manual\/en\/reserved.variables.files.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">$_FILES<\/a> global de PHP y luego cargarse. Sin embargo, al hacer eso, es importante asegurarse de que est\u00e1 cargando un archivo con <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-02-save-part2-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">la extensi\u00f3n de archivo correcta<\/a><\/strong> (como m\u00ednimo).<\/p>\n<pre><code>&lt;?php\n\n$file_type = explode('.', $filename);\n$file_type = strtolower($file_type[count($file_type) - 1]);\nif ('pdf' !== $file_type) {\n  \/\/ Give your feedback of choice here.\n}\n<\/code><\/pre>\n<p>Si el tipo de archivo no es un PDF, puede arrojar un error, simplemente regresar (aunque no soy un fan\u00e1tico de esto) o <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-03-save-part3-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">dar algunos comentarios al usuario<\/a><\/strong> (lo cual soy fan\u00e1tico de hacer).<\/p>\n<pre><code>&lt;?php\n\nif ($uploadFile['error']) {\n  \/\/ Your preferred method of feedback here.\n}<\/code><\/pre>\n<p>Sin embargo, el \u00faltimo paso es obtener el archivo en el cargador de medios.<\/p>\n<h3>3 Cargarlo en el cargador de medios<\/h3>\n<p>El \u00faltimo paso en todo esto es obtener el archivo en el cargador de medios. Para hacer esto, necesita varias cosas del n\u00facleo de WordPress:<\/p>\n<ol>\n<li>la biblioteca file.php,<\/li>\n<li>una matriz de archivos adjuntos necesaria para decirle a WordPress lo que se est\u00e1 agregando,<\/li>\n<li>una funci\u00f3n API de WordPress, <strong>wp_insert_attachment<\/strong><\/li>\n<li>redirigir de nuevo a la p\u00e1gina de llamada<\/li>\n<\/ol>\n<p>Suena como mucho, \u00bfverdad? No es tan malo.<\/p>\n<p>Normalmente agrupo la inclusi\u00f3n de la biblioteca de archivos de WordPress y <strong>wp_insert_attachment<\/strong> en un solo bloque.<\/p>\n<p>Notar\u00e1 que configuro el tipo MIME en <strong>pdf<\/strong> y me aseguro de que el t\u00edtulo no incluya nada excepto el nombre del archivo. Despu\u00e9s de eso, uso <a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/wp_insert_attachment\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wp_insert_attachment<\/a> para cargar el archivo en la biblioteca multimedia.<\/p>\n<\/p>\n<p>El c\u00f3digo completo para eso es <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-05-save-part5-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">el siguiente:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\nrequire_once(ABSPATH. \"wp-admin\". '\/includes\/file.php');\n$attachment  = array(\n    'post_mime_type' =&gt; 'pdf',\n    'post_title'     =&gt; preg_replace('\/.[^.]+$\/', '', $filename),\n    'post_status'    =&gt; 'inherit'\n);\n$attachment_id = wp_insert_attachment($attachment, $uploadFile['file']);\n<\/code><\/pre>\n<p>Despu\u00e9s de eso, redirijo de nuevo a la p\u00e1gina que inici\u00f3 todo esto (que suele ser la p\u00e1gina de administraci\u00f3n que vimos en la publicaci\u00f3n anterior). Para esto, tomo el _wp_http_referer de la matriz <a href=\"https:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">$_REQUEST<\/a> <strong>de<\/strong> PHP .<a href=\"https:\/\/php.net\/manual\/en\/reserved.variables.request.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external\"><\/a><\/p>\n<pre><code>&lt;?php\nwp_safe_redirect(\n    $_REQUEST['_wp_http_referer'],\n    301\n);\nexit;\n<\/code><\/pre>\n<p>Y eso <a href=\"https:\/\/gist.github.com\/tommcfarlin\/51b158a2cbc4052bef12cc059837a6ee#file-06-save-part6-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">redirigir\u00e1<\/a> al usuario a la p\u00e1gina de donde vino.<\/p>\n<h2>Y El Archivo Se Sube<\/h2>\n<p>En este punto, hemos establecido lo que queremos hacer:<\/p>\n<ol>\n<li>Ofrezca una experiencia decente del lado del cliente,<\/li>\n<li>Subi\u00f3 el archivo a la biblioteca de medios (con oportunidades para ofrecer comentarios)<\/li>\n<li>Y redirigido de nuevo a la p\u00e1gina que comenz\u00f3 todo.<\/li>\n<\/ol>\n<p>De acuerdo, hay mucho espacio para comentarios en esto, y lo insto a que lo adapte seg\u00fan sea necesario para su c\u00f3digo, pero la base de lo que necesita se debe proporcionar tanto <a href=\"https:\/\/wordpress.mediadoma.com\/es\/subir-archivos-en-wordpress-revisado-parte-1-el-lado-del-cliente\/\" title=\"en la publicaci\u00f3n anterior\">en la publicaci\u00f3n anterior<\/a> como en esta publicaci\u00f3n.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fuente de grabaci\u00f3n:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Un ejemplo de c\u00f3digo del lado del servidor necesario para cargar un archivo a trav\u00e9s de WordPress (y Media Uploader).<\/p>\n","protected":false},"author":1,"featured_media":164785,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[892,840,861],"tags":[1172],"class_list":["post-229884","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo","category-tutoriales","category-wordpress-2","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/229884","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/comments?post=229884"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/229884\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/164785"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=229884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=229884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=229884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}