Menú
gratis
Registro
Hogar  /  Programas/ Subida de archivos al servidor mediante PHP. Principales vulnerabilidades y formas de evitarlas

Subir archivos al servidor usando PHP. Principales vulnerabilidades y formas de evitarlas

De hecho, la carga de archivos es una característica importante de muchos de los sitios y aplicaciones web que utilizamos a diario. En este artículo te mostraré otra forma de cargar archivos usando PHP.

Requisitos

Subir archivos al servidor no es difícil, pero hay algunos pequeños detalles que se deben tener en cuenta, de lo contrario la carga no se completará. Primero, debe asegurarse de que PHP esté configurado para permitir descargas. revisa tu php.ini archivo y verifique la directiva file_uploads, que debe configurarse en En.

Una vez que haya configurado las configuraciones para permitir que el servidor acepte archivos cargados, puede centrar su atención en el componente HTML. Los formularios se utilizan para cargar archivos desde el lado HTML. Es extremadamente importante que sus formularios utilicen el método POST y tengan el atributo enctype establecido en multipart/form-data.

<acción del formulario = "upload.php" método = "post" enctype = "multipart/form-data" >

Escribir un script para el proceso de arranque

El proceso de descarga de un archivo en general se ve así:

  • El visitante ve una página HTML con un formulario para descargar archivos;
  • El visitante selecciona el archivo que desea descargar en el formulario;
  • El navegador codifica el archivo y lo envía como parte de la solicitud POST;
  • PHP recibe el formulario de representación, decodifica el archivo y lo guarda en un directorio temporal en el servidor;
  • A continuación, el script PHP mueve el archivo a una ubicación de almacenamiento permanente.

Por lo tanto, para que el visitante pueda subir un archivo, es necesario un formulario HTML, que se le proporcionará al usuario, y un script PHP que se encargue de subir los archivos al servidor.

formulario HTML

Los formularios HTML proporcionan una interfaz a través de la cual el usuario inicia la carga de archivos. Recuerde, el elemento del formulario debe tener método = POST y no debe codificar los datos cuando se envían al servidor; el atributo enctype está establecido en multipart/form-data. Colocamos un elemento de entrada para seleccionar un archivo. Al igual que con cualquier otro elemento de formulario, es muy importante para nosotros especificar el valor del atributo de nombre para que se pueda hacer referencia a él en el script PHP que procesa el formulario.

El formulario de carga de archivos se ve así:

1
2
3
4
5






Vale la pena señalar que diferentes navegadores muestran el campo del archivo de manera diferente. Esto no es un problema, ya que los usuarios están acostumbrados a cómo se ve el campo de selección de archivos en su navegador favorito. Sin embargo, si la apariencia es importante para ti, te recomiendo que leas este artículo.

script de descarga PHP

La información sobre el archivo descargado se encuentra en la matriz multidimensional $_FILES. Esta matriz está indexada por los nombres de los archivos colocados en el campo HTML del formulario. La matriz contiene la siguiente información sobre cada archivo:

  • $_FILES["myFile"]["name"] - nombre del archivo original;
  • $_FILES["myFile"]["type"] - tipo de archivo MIME;
  • $_FILES["myFile"]["size"] - tamaño del archivo (en bytes);
  • $_FILES["miArchivo"]["tmp_name"]— nombre del archivo temporal;
  • $_FILES["miArchivo"]["error"]— código de cualquier error durante la transmisión.

La función move_uploaded_file() mueve un archivo cargado de una ubicación temporal a una permanente. Siempre debes usar move_uploaded_file() en lugar de copy() y rename() para este propósito, ya que realiza una verificación adicional para garantizar que el archivo realmente se cargó mediante la solicitud HTTP POST.

Si planea guardar el archivo con un nombre real, deberá seguir algunas reglas. El nombre del archivo no debe contener caracteres como barras, que podrían afectar la ubicación. El nombre no debe coincidir con el nombre de los archivos existentes para no sobrescribirlos. Reemplazamos cualquier carácter que no sea una letra o un número con un guión bajo y agregamos un número de "lupa" si los nombres coinciden.

Recibir y manejar cargas de archivos usando PHP se ve así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

//directorio donde guardar el archivo
definir ("UPLOAD_DIR", "/srv/www/uploads/");

if (! vacío ($_FILES [ "miArchivo" ] ) ) (
$miArchivo = $_FILES [ "miArchivo" ] ;

// comprueba si hay errores durante la carga
si ($miArchivo [ "error" ] !== UPLOAD_ERR_OK) (
eco "

Ha ocurrido un error.

" ;
salida ;
}

// proporcionar un nombre de archivo seguro
$nombre = preg_replace ("/[^A-Z0-9._-]/i", "_", $myFile [ "nombre" ]);

// si los nombres de los archivos coinciden, agrega un número
$yo = 0 ;
$partes = información de ruta ($nombre);
mientras (archivo_existe (UPLOAD_DIR. $nombre)) (
$yo++;
$nombre = $partes [ "nombre de archivo" ] .
}

"-" .
$yo.
"."
.
$partes["extensión"];
salida ;
}

// mueve el archivo a una ubicación de almacenamiento permanente
$éxito = move_uploaded_file ($myFile [ "tmp_name" ] ,

SUBIR_DIR.

$nombre); si (! $éxito) (

" ;
}

Primero verificamos el archivo para ver si se descargó sin errores. Luego definimos un nombre de archivo seguro y luego colocamos el archivo en el directorio final usando move_uploaded_file(). Y al final configuramos los derechos de acceso al archivo.

Problemas de seguridad

La mayoría de nosotros no permitiríamos que se descarguen y almacenen archivos completamente desconocidos en nuestro servidor, pero desafortunadamente en la situación actual este es el caso. Por lo tanto, debe describir varios pasos que minimizarán los riesgos de seguridad asociados con la descarga de archivos.

Uno de ellos es comprobar el tipo de archivo que se está descargando. Depender del valor almacenado en $_FILES[“myFile”][“type”] “no es bueno”, ya que las extensiones en los nombres de los archivos se pueden falsificar fácilmente. En tales situaciones, es mejor analizar el contenido del archivo; por ejemplo, usar la función exif_imagetype() le permite determinar si el archivo descargado es realmente una imagen con extensión GIF, JPEG, etc. Si exif_imagetype() no está disponible (la función requiere una extensión Exif), entonces puedes usar getimagesize() . La matriz devuelta contendrá las dimensiones y el tipo de la imagen.

1
2
3
4
5
6
7

...
// el archivo debe ser una imagen
$fileType = exif_imagetype ($_FILES [ "myFile" ] [ "tmp_name" ] );
$ permitido = matriz (IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG);
if (! in_array ($tipo de archivo, $permitido) ) (
// el tipo de archivo no está permitido
...

Para archivos que no sean gráficos, puede usar Exec() para llamar a la utilidad Archivo Unix. Esta utilidad determina el tipo de archivo.

Otro paso que puede tomar para mejorar la seguridad al cargar archivos es imponer límites estrictos al tamaño total de la solicitud POST y la cantidad de archivos que se pueden cargar. Para hacer esto, debe especificar el valor apropiado para las directivas upload_max_size, post_max_size y max_file_uploads en el archivo. php.ini.

  • upload_max_size define el tamaño máximo de los archivos cargados.
  • Además del tamaño de carga, puedes limitar el tamaño de una solicitud POST gracias a la directiva post_max_size.
  • max_file_uploads es una directiva más nueva (agregada en la versión 5.2.12) que limita la cantidad de archivos cargados.

post_max_size = 8M
subir_max_size = 2M
max_file_uploads = 20

El tercer paso (un tanto exótico) que puedes dar para minimizar el riesgo al descargar archivos es escanear con un escáner antivirus. Vale la pena agregar que este tema es muy serio, por lo que se le debe prestar suficiente atención al desarrollar aplicaciones web.

Así sucede subir archivos al servidor usando PHP. Si tiene algún comentario o adición a este artículo, déjelo en los comentarios. ¡Gracias por leer!

PD¿Tiene un sitio web basado en el motor Joomla y utiliza servicios de hosting? Para aquellos que logran el máximo rendimiento en sus proyectos de Internet, vale la pena probar el alojamiento con Joomla. El alojamiento especializado para sitios web Joomla garantizará un funcionamiento estable y eficiente, y los planes de tarifas favorables no dejarán indiferente a nadie.

Cuando un sitio requiere permitir que un usuario cargue sus archivos (por ejemplo, fotos o avatares) y luego los almacene en el servidor, inmediatamente surgen una serie de problemas de seguridad.

La primera y más obvia es nombres de archivos. Deben comprobarse en busca de caracteres especiales, ya que el usuario puede falsificar una solicitud HTTP, como resultado de lo cual el archivo descargado tendrá un nombre, por ejemplo, ../index.php. y cuando intente guardarlo, se sobrescribirá el índice raíz. Además, el nombre puede contener letras rusas en codificación windows-1251 o koi-8, que no se guardarán correctamente en el sistema de archivos. Conclusión: debe guardar el archivo no con el nombre con el que el usuario lo descargó, sino con uno aleatorio, por ejemplo, un hash MD5 del nombre del archivo, el tiempo de descarga y la IP del usuario. El nombre de este archivo se encuentra en algún lugar de la base de datos y luego proporcione el archivo como un script, que primero generará el encabezado Content-disposition: adjunto; nombre de archivo="nombre de archivo".

Segundo problema - No se puede confiar en la extensión o el tipo MIME., se pueden falsificar si se desea. Por lo tanto, si el tipo de archivo es importante, se debe verificar que cumpla con el formato que ya está en el servidor (para imágenes, la función getimagesize del módulo GD es buena, para otros tipos, leer encabezados) y rechazar aquellos archivos cuyo formato no coincide.

Y finalmente, el tercer problema, el más importante. Hay varias soluciones aquí. La primera es si pretendes descargar sólo ciertos tipos de archivos (por ejemplo, el avatar sólo puede ser una imagen en formato PNG, JPG, GIF) y rechaza todo lo que no sea adecuado. Pero a veces es necesario permitir que se carguen todo tipo de archivos. Entonces surge la segunda opción: verificar la extensión del archivo descargado y, si no es seguro, cambiarle el nombre (por ejemplo, reemplazar la extensión de .php a .phps hará que el script no se ejecute, pero se mostrará su código). con resaltado de sintaxis). La principal desventaja de esta solución es que puede resultar que algún servidor esté configurado para ejecutar scripts con una extensión inusual, por ejemplo, .php3, y no será posible filtrarlo. Y finalmente, la tercera opción es deshabilitar el procesamiento de scripts, por ejemplo a través de .htaccess:

RemoveHandler .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml
Aplicación AddType/x-httpd-php-source .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp

Sin embargo, tenga en cuenta que el archivo .htaccess solo afecta a Apache (e incluso entonces su uso debe estar habilitado en la configuración), y en otros servidores será ignorado. (Esto es especialmente importante para los scripts que se publican públicamente: tarde o temprano habrá un usuario con algún tipo de IIS que no tomará las medidas adecuadas, por lo que es mejor combinar este método con el anterior).

Y por último: después de leer este texto, es posible que desee almacenar los archivos de usuario en una base de datos. No deberías hacer esto: aunque parezca una solución sencilla, deberías tener en cuenta que los motores de búsqueda modernos indexan no sólo páginas HTML normales, sino también otros tipos de archivos. Y en el momento en que pase el robot de búsqueda, la carga en el servidor SQL aumentará considerablemente debido a la necesidad de transferir una gran cantidad de datos a la vez, lo que provocará problemas en el funcionamiento del sitio.

En el último artículo lo comentamos contigo. Sin embargo, ya les dije que ¡está absolutamente prohibido usar el código que se discutió allí! Y en este artículo hablaremos de seguridad al subir archivos al servidor en PHP.

Déjame recordarte el código que vimos ayer:

$uploadfile = "imágenes/".$_FILES["algún nombre"]["nombre"];
move_uploaded_file($_FILES["algún nombre"]["tmp_name"], $uploadfile);
?>

De hecho, en este momento se puede descargar absolutamente cualquier cosa: cualquier archivo ejecutable, scripts, páginas HTML y otras cosas muy peligrosas. Por lo tanto, debes revisar los archivos descargados con mucho cuidado. Y ahora comenzaremos a comprobarlos a fondo.

Dado que puede haber muchas opciones diferentes para las tareas, consideraremos la opción de cargar una imagen simple, que debe estar sujeta a las siguientes restricciones:

  1. Tipo - sólo jpg (jpeg).
  2. Tamaño - menos 100 KB.
"de acuerdo con estos requisitos:

$lista negra = matriz(".php", ".phtml", ".php3", ".php4", ".html", ".htm");
foreach ($lista negra como $elemento)
if(preg_match("/$item\$/i", $_FILES["algún nombre"]["nombre"])) salir;
$tipo = $_FILES["algún nombre"]["tipo"];
$tamaño = $_FILES["algún nombre"]["tamaño"];
if (($tipo!= "imagen/jpg") && ($tipo!= "imagen/jpeg")) salir;
si ($tamaño > 102400) sale;
$uploadfile = "imágenes/".$_FILES["algún nombre"]["nombre"];
move_uploaded_file($_FILES["algún nombre"]["tmp_name"], $uploadfile);
?>

Ahora déjame explicarte en detalle lo que está sucediendo aquí. Primero que nada nosotros comprobar la extensión del archivo descargado. si representa secuencia de comandos PHP, entonces simplemente no nos saltamos dicho archivo. A continuación obtenemos tipo MIME y tamaño. Los comprobamos para asegurarnos de que cumplen nuestras condiciones. Si todo está bien, descargamos el archivo.

Probablemente te preguntes: " ¿Por qué es necesario comprobar tanto la extensión como el tipo MIME?". Es muy importante entender que esto está lejos de ser lo mismo. Si un atacante intenta enviar archivo PHP a través del navegador, entonces uno Comprobaciones tipo MIME suficiente para que su intento fracasara. Pero si escribe algún script que genere una solicitud y envíe un archivo malicioso, esto no será suficiente. ¿Por qué? Pero porque tipo MIME¡lo establece el cliente, no el servidor! Y de hecho, un atacante puede poner cualquier tipo MIME(y fotos también), pero al mismo tiempo enviar secuencia de comandos PHP. Y es precisamente este astuto intento el que desbaratamos al comprobar la extensión del archivo.

Diré de inmediato que este código está lejos de 100% protección (100% simplemente no existe), sin embargo, descifrar dicho código será muy, muy difícil, por lo que puedes decir con seguridad que has proporcionado alta seguridad al cargar archivos al servidor a través de PHP.

1 53

grisgato

1 respuesta:

El modelo de procesador descrito en el manual del procesador Intel/AMD es un modelo bastante tosco para real moderno motor de ejecución del kernel. En particular, el concepto de registros de procesador no es cierto; no existen registros EAX o RAX.

Una de las tareas principales del decodificador de instrucciones es convertir instrucciones x86/x64 heredadas en microoperaciones, Instrucciones de procesador tipo RISC. Pequeñas instrucciones que son fáciles de ejecutar simultáneamente y pueden aprovechar múltiples subbloques de ejecución. Permite la ejecución simultánea de hasta 6 instrucciones.

Para que esto funcione, también se virtualiza el concepto de registros del procesador. El decodificador de instrucciones asigna un registro de un gran banco de registros. cuando las instrucciones pensiones, el valor de este registro asignado dinámicamente se vuelve a escribir en cualquier registro que contenga actualmente el valor de, por ejemplo, PAX.

Para que esto funcione sin problemas y de manera eficiente, permitiendo que muchas instrucciones se ejecuten simultáneamente, es muy importante que estas operaciones no tengan interdependencias. Y lo peor que puede tener es que el valor del registro dependa de otras instrucciones. El registro EFLAGS es notorio y muchas instrucciones lo modifican.

El mismo problema con cómo tú Cómoél a trabajar. El gran problema es que requiere que se concatenen dos valores de registro cuando se elimina la instrucción. Creando una dependencia de datos que obstruirá el kernel. Al forzar que los 32 bits superiores sean 0, esta dependencia desaparece instantáneamente y ya no es necesario fusionarse. Velocidad de deformación 9.

En este artículo analizaremos en detalle el mecanismo para cargar imágenes al servidor usando PHP sin recurrir a componentes y frameworks de terceros. Aprendamos cómo descargar imágenes de forma segura no solo desde la máquina local del usuario, sino también desde archivos remotos a través de un enlace. Escribiré todos los ejemplos de código en un estilo de procedimiento para que puedas leer el código más rápido y no saltar de un método a otro. El manual es completamente original y no pretende ser ningún tipo de presentación académica..

§1.

Principios generales La secuencia completa de carga de una imagen al servidor se puede mostrar de la siguiente manera:configurando php.inirecibiendo archivocontrol de seguridadvalidación de datos guardando en el disco

. El proceso de descargar una imagen desde la computadora del usuario o mediante URL no es diferente, excepto por el método para obtener la imagen y guardarla. El esquema general para subir una imagen al servidor es el siguiente:

Para validar una imagen por URL, usaremos la función getimagesizefromstring(), ya que cURL la descargará en una variable para su posterior manipulación. Dado que estamos subiendo imágenes al servidor, sería bueno verificar ciertos parámetros:, ancho, altura tipo fotos, archivo en bytes. Depende de la lógica de su aplicación, pero para mayor claridad, en este tutorial verificaremos todos los parámetros descritos anteriormente.

§2.

Reglas de seguridad La seguridad para descargar imágenes se reduce a evitar que código externo llegue al servidor y se ejecute. En la práctica, cargar imágenes es el punto más vulnerable en las aplicaciones PHP:, golpeado por scripts de shell, escribir código malicioso en archivos binarios sustitución de datos EXIF

. Para evitar la mayoría de los métodos de piratería, debe cumplir con las siguientes reglas: A No
datos de confianza de $_FILES; A b
comprobar el tipo MIME de una imagen desde la función getimagesize();
generar un nuevo nombre y extensión en el archivo descargado;
d prohibir la ejecución de scripts PHP en la carpeta con imágenes; A d
insertar datos de usuario mediante require e include;

Para $_FILES utilice is_uploaded_file() y move_uploaded_file().

Si tiene algo que agregar a las "Reglas de seguridad", deje sus comentarios o enlaces a artículos de seguridad en los comentarios de esta guía y los publicaré en este párrafo.

§3. configuración de php.ini», « PHP le permite ingresar ciertos valores de configuración en el proceso de carga de cualquier archivo. Para hacer esto, necesitas encontrar los bloques " Límites de recursos Manejo de datos" Y "

Cargas de archivos", y luego edite los siguientes valores según sea necesario: ; Tiempo máximo de ejecución del script en segundos max_execution_time = 60 ; Consumo máximo de memoria para un script límite_memoria = 64M ; Tamaño máximo permitido de datos enviados mediante el método POST post_max_size = 5M ; Permiso para subir archivos file_uploads = Activado ; Carpeta para almacenar archivos durante la descarga. upload_tmp_dir = inicio/usuario/temp ; Tamaño máximo de archivo de carga subir_max_filesize = 5M

; Número máximo permitido de archivos descargados simultáneamente configuración de php.ini max_file_uploads = 10

El archivo de configuración php.ini siempre debe configurarse de acuerdo con la lógica de negocio de la aplicación web que se está desarrollando. Por ejemplo, planeamos descargar no más de diez archivos de hasta 5 MB, lo que significa que necesitaremos ~50 MB de memoria. Además, necesitamos saber el tiempo máximo para descargar un archivo desde la máquina local y desde un enlace, para establecer un tiempo de ejecución de script suficiente en max_execution_time y no asustar a los usuarios con errores.

§4.

Cargando imágenes desde el formulario Ahora no consideraremos cargar varios archivos al servidor, solo analizaremos la mecánica de carga usando el ejemplo de un archivo. Entonces, para descargar una imagen desde la computadora del usuario, debe usar un formulario HTML para enviar el archivo a un script PHP usando el método POST y especificar el método de codificación de datos. enctype="multipart/form-data"

Descargar Para el campo de selección de archivos usamos el nombre nombre="subir" en nuestro formulario HTML, aunque puede ser cualquier cosa. Después de enviar un archivo al script PHP file-handler.php, se puede interceptar usando una variable superglobal$_FILES["cargar"]

con el mismo nombre, que contiene información sobre el archivo en una matriz: matriz ( => imagen.jpg // nombre del archivo original => imagen/jpeg // tipo de archivo MIME => inicio\usuario\temp\phpD07E.tmp // archivo binario => 17170 => 0 // código de error)

// tamaño del archivo en bytes No todos los datos de$_FILES Se puede confiar: el tipo MIME y el tamaño del archivo pueden ser falsificados, ya que se forman a partir de una respuesta HTTP, y no se debe confiar en la extensión del nombre del archivo debido al hecho de que detrás de él se puede ocultar un archivo completamente diferente. Sin embargo, a continuación debemos verificar si nuestro archivo se cargó correctamente y si se cargó en absoluto. Para hacer esto, debe verificar si hay errores en$_FILES["cargar"]["error"] y asegúrese de que el archivo se cargue usando el método POST usando la función is_uploaded_file()

. Si algo no sale según lo planeado, mostramos el error en la pantalla.// Reescribir variables por conveniencia $filePath = $_FILES ["cargar" ]["tmp_name" ]; $errorCode = $_FILES ["cargar" ]["error" ];// Comprobar errores if ($errorCode !== UPLOAD_ERR_OK || ! is_uploaded_file ($filePath )) (// Matriz con nombres de errores $mensajesdeerror = [ UPLOAD_ERR_INI_SIZE =>"El tamaño del archivo ha excedido el valor upload_max_filesize en la configuración de PHP". , UPLOAD_ERR_FORM_SIZE =>"El tamaño del archivo cargado superó el valor MAX_FILE_SIZE en el formulario HTML". "El archivo descargado se recibió sólo parcialmente.", UPLOAD_ERR_NO_FILE => "El archivo no se cargó.", UPLOAD_ERR_NO_TMP_DIR => "Falta la carpeta temporal"., UPLOAD_ERR_CANT_WRITE => "Error al escribir el archivo en el disco"., UPLOAD_ERR_EXTENSION => "La extensión PHP ha dejado de descargar el archivo"., ]; // Establece un error desconocido$mensaje desconocido = "Se produjo un error desconocido al descargar el archivo".; // Si no hay ningún código de error en la matriz, digamos que el error es desconocido$outputMessage = isset ($errorMessages [$errorCode])? $mensajesdeerror [$códigodeerror] : $mensajedesconocido;// Imprime el nombre del error

morir ($mensajedesalida); ) Para evitar que un atacante descargue código malicioso incrustado en la imagen, no se puede confiar en la función obtener tamaño de imagen() , que también devuelve el tipo MIME. La función espera que el primer argumento sea un enlace a un archivo de imagen válido. . Puede determinar el tipo MIME real de una imagen utilizando la extensión FileInfo. El siguiente código comprobará la presencia de la palabra clave. imagen

en el tipo de nuestro archivo descargado y si no está generará un error:// Crea un recurso FileInfo

$fi = finfo_open(FILEINFO_MIME_TYPE); // Obtener el tipo MIME $mime = (cadena) finfo_file ($fi, $filePath); ); Para evitar que un atacante descargue código malicioso incrustado en la imagen, no se puede confiar en la función En esta etapa ya podemos subir a nuestro servidor absolutamente cualquier imagen que haya pasado la verificación del tipo MIME, pero para subir imágenes en función de determinadas características, necesitamos validarlas mediante la función , al que alimentamos el propio archivo binario$_FILES["cargar"]["tmp_name"]

. Como resultado, obtendremos una matriz de máximo 7 elementos: Matriz ( => 1280 // ancho => 768 // alto => 2 // tipo => ancho="1280" alto="768" // atributos para HTML => 3 => 8 // profundidad de color // modelo de color

=> imagen/jpeg // tipo MIME) Dado que estamos subiendo imágenes al servidor, sería bueno verificar ciertos parámetros:, ancho Para validar aún más la imagen y trabajar en ella, sólo necesitamos conocer 3 valores: fotos, Y archivo (para calcular el tamaño, use la función tamaño de archivo()

para un archivo binario de una carpeta temporal).//Escribe el resultado de la función en una variable $imagen = getimagesize($filePath);$límiteBytes = 1024 * 1024 * 5 ; $ancho límite = 1280 ; $alturalímite = 768 ; // Verifica los parámetros necesarios si (tamaño de archivo ($filePath) > $limitBytes) muere (

"El tamaño de la imagen no debe exceder los 5 MB." ); if ($imagen > $limitHeight ) die(); if ($imagen > $limitWidth) muere();, que funciona en modo seguro. Antes de mover un archivo, no debes olvidar generar nombre aleatorio y extensión a partir del tipo de imagen para nuestro archivo. Esto es lo que parece:

// Genera un nuevo nombre de archivo basado en el hash MD5$nombre = md5_file ($filePath); // Acortar .jpeg a .jpg// Mueve la imagen con un nuevo nombre y extensión a la carpeta /pics if (! move_uploaded_file ($filePath, __DIR__. "/pics/". $nombre. $formato)) ( die ( "Se produjo un error al escribir la imagen en el disco".); }

Esto completa la carga de la imagen. Para una carga de archivos más cómoda, puedes utilizar la clase UploadedFile del paquete Symfony HttpFoundation, que es un contenedor para No todos los datos de y también guarda el archivo a través de ); if ($imagen > $limitHeight ) die(); if ($imagen > $limitWidth) muere();.

§5.

Subir una imagen a través de un enlace Para descargar una imagen a través de un enlace, necesitamos la biblioteca cURL, que funciona con recursos remotos. Usándolo descargaremos el contenido en una variable. Por un lado, puede parecer que sería adecuado para estos fines archivo_get_contents() , pero en realidad no podremos controlar la cantidad de datos descargados y normalmente manejar todos los errores que surjan. Para que cURL descargue correctamente los datos que necesitamos: permitir seguir redirecciones , habilitar la verificación certificado , indicar tiempo máximo

Rendimiento de cURL (formado por el volumen de datos descargados y la velocidad promedio de trabajo con el recurso). A continuación se muestra cómo descargar correctamente un archivo a una variable con los parámetros necesarios:// De alguna manera obtengo el enlace $url = "https://site.ru/imagen.jpg" ;// Verifica HTTP en la dirección del enlace if (! preg_match ("/^https?:/i" , $url ) && filter_var ($url , FILTER_VALIDATE_URL)) ( morir (); } "Proporcione un enlace válido al archivo remoto".// Ejecuta cURL con nuestro enlace $ch = curl_init ($url);// Especificar la configuración para cURL curl_setopt_array ($ch, [// Especifica el tiempo máximo de ejecución de cURL CURLOPT_TIMEOUT => 60,// Permitir que sigan redirecciones CURLOPT_FOLLOWLOCATION => 1,// Permitir que el resultado se escriba en una variable CURLOPT_RETURNTRANSFER => 1,//Activar el indicador de carga de datos CURLOPT_NOPROGRESS => 0,// Establece el tamaño del buffer en 1 KB CURLOPT_BUFFERSIZE => 1024, // Escribamos una función para contar los datos descargados// Más detalles: http://stackoverflow.com/a/17642638 CURLOPT_PROGRESSFUNCTION => función ($ch, $dwnldSize, $dwnld, $upldSize, $upld) (// Cuando se descargan más de 5 MB, cURL cancelará si ($dwnld > 1024 * 1024 * 5 ) ( retorno - 1 ; ) ), CURLOPT_SSL_VERIFYPEER => 1, // Verifica el nombre del certificado y si coincide con el host especificado (predeterminado) CURLOPT_SSL_VERIFYHOST => 2, // Especifica el certificado de verificación // Descargar: https://curl.haxx.se/docs/caextract.html CURLOPT_CAINFO => __DIR__. "/cacert.pem" , ]); $raw = curl_exec($ch);//Descargar datos a la variable $info = curl_getinfo ($ch);// Obtener información sobre la operación $error = curl_errno($ch); // Anota el último código de error// Finaliza la sesión de cURL

curl_close($ch); Si todo salió bien y cURL se completó en 60 segundos, entonces el contenido del enlace se descargará en una variable$crudo . Además, la función curl_getinfo()

con el mismo nombre, que contiene información sobre el archivo en una matriz: devolverá información sobre la solicitud realizada, de donde podremos obtener información adicional para analizar el trabajo con recursos remotos: => imagen/jpeg => 200 // tipo MIME del tipo de contenido => 0 // último código HTTP => 0.656 // número de redirecciones => 0.188 // tiempo total de ejecución de cURL => 4504 // hora de conectarse al host => 4504 // tamaño real de los datos recibidos /* ... */ )

// tamaño de datos de Content-Length A continuación debemos comprobar si hay algún error en curl_errno() Si todo salió bien y cURL se completó en 60 segundos, entonces el contenido del enlace se descargará en una variable y asegúrese de que el recurso devuelva un código HTTP de 200; de lo contrario, diremos que no se encontró nada en tal o cual URL. Después de todo comprueba la variable. transferir a obtener tamaño de imagen de cadena()

y trabajamos según el esquema probado, como en el caso de cargar imágenes desde el formulario.

Tenga en cuenta que validamos el tamaño del archivo en el momento de recibir los datos, ya que no podemos confiar en curl_getinfo() al 100%, ya que los valores content_type, http_code, download_content_length se forman en función de los encabezados HTTP recibidos. Descargar el archivo completo y luego verificar la cantidad de bytes requerirá mucho tiempo y memoria. Por lo tanto, controlamos el tamaño de los datos recibidos usando la opción CURLOPT_PROGRESSFUNCTION: tan pronto como cURL reciba más datos que nuestro límite, dejará de funcionar y arrojará un error CURLE_ABORTED_BY_CALLBACK.// Comprobar errores de cURL y disponibilidad de archivos si ($error === CURLE_OPERATION_TIMEDOUT) muere ("Límite de espera excedido." ); si ($error === CURLE_ABORTED_BY_CALLBACK) muere ("El tamaño no debe exceder los 5 MB". ); si ($info ["http_code" ] !== 200 ) muere (); en el tipo de nuestro archivo descargado y si no está generará un error:"El archivo no está disponible." $fi = finfo_open(FILEINFO_MIME_TYPE);// Obtiene el tipo MIME usando el contenido de $raw $mime = (cadena) finfo_buffer ($fi, $raw);// Cerrar el recurso FileInfo finfo_close($fi);// Verifique la palabra clave de la imagen (imagen/jpeg, imagen/png, etc.) si (strpos($mime, "imagen") === falso) muere(); // Tomar datos de la imagen de su contenido.$imagen = getimagesizefromstring($raw); // Establecer restricciones para imágenes$ancho límite = 1280 ; $alturalímite = 768 ; $imagen = getimagesize($filePath); si ($imagen > $limitHeight ) muere ( "La altura de la imagen no debe exceder los 768 píxeles".); si ($imagen > $limitWidth ) muere ( "El ancho de la imagen no debe exceder los 1280 píxeles".); // Genera un nuevo nombre a partir del hash MD5 de la imagen$nombre = md5($raw); // Genera una extensión de archivo basada en el tipo de imagen$extensión = image_type_to_extension($imagen); // Acortar .jpeg a .jpg$formato = str_replace ("jpeg", "jpg", $extensión); // Guarda la imagen con un nuevo nombre y extensión en la carpeta /pics if (! file_put_contents (__DIR__ . "/pics/" . $nombre . $formato , $raw )) ( morir ( "Se produjo un error al guardar la imagen en el disco".); }

Para guardar la imagen en el disco, puede utilizar archivo_put_contents() que escribirá el contenido en un archivo. Crearemos un nuevo nombre de archivo usando la función md5(), y hagamos una extensión de tipo_imagen_a_extensión(). Ahora podemos descargar cualquier imagen desde el enlace.

§6.

Configurar la selección de múltiples archivos En este párrafo, veremos formas de descargar varias imágenes a la vez desde la máquina local del usuario y mediante enlaces remotos. Para enviar enlaces utilizamos$_POST y transferirle todos los datos usando la etiquetaárea de texto No todos los datos de. Para cargar archivos desde el formulario, continuaremos trabajando con

. Nuestro nuevo formulario HTML será ligeramente diferente del anterior. Para el campo de selección de archivos usamos el nombre Al final del nombre del campo de selección de archivos. Se agregaron llaves y atributos. múltiple No todos los datos de, que permite al navegador seleccionar varios archivos. Todos los archivos se descargarán nuevamente a la carpeta temporal si no hay errores en php.ini. Puedes interceptarlos en

, pero esta vez la variable superglobal tendrá una estructura inconveniente para procesar datos en una matriz. Este problema se puede solucionar mediante pequeñas manipulaciones con la matriz:// Cambiar la estructura $_FILES foreach ($_FILES ["cargar" ] como $clave => $valor ) ( foreach ($valor como $k => $v ) ( $_FILES ["cargar" ][$k ][$clave ] = $v ; )// Eliminar claves antiguas sin configurar ($_FILES ["cargar" ][$clave]); )// Carga todas las imágenes en orden foreach ($_FILES ["cargar" ] como $k => $v ) (// Carga un archivo a la vez

$_FILES ["cargar" ][$k ]["tmp_name" ]; y transferirle todos los datos usando la etiqueta$_FILES ["cargar" ][$k ]["error" ]; ) Para el campo de selección de archivos usamos el nombre Para descargar varias imágenes por URL, transferiremos nuestros enlaces a través de con nombre, donde se pueden especificar separados por un espacio o en una nueva línea. Función preg_split y formará una matriz a través de la cual deberá realizar un bucle y enviar cada URL válida al controlador.

$datos = preg_split ("/\s+/" , $_POST ["cargar" ], - 1 , PREG_SPLIT_NO_EMPTY); foreach ($datos como $url) ( // Validar y cargar la imagen por URL }