Ficheros en PHP

Iniciado por Xt3mP, Agosto 13, 2010, 01:36:34 AM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Agosto 13, 2010, 01:36:34 AM Ultima modificación: Marzo 27, 2014, 06:07:35 PM por Expermicid
Archivos.

¿Qué explicaré?
Carga de ficheros (Tanto permisos, nombre, tipo, tamaño, etc) y funciones acerca de archivos (copiar, mover, eliminar, crear, etc).

Quisiera comenzar explicando la diferencia entre $_FILES y $HTTP_POST_FILES.
Las dos son variables que contienen la misma información cuando se hace una carga a el script (en este caso, subir un archivo), pero la diferencia es que $HTTP_POST_FILES no es una variable "superglobal", con esto quiero decir que tál vez contenga la misma información del fichero pero no se puede acceder en todo el script a ella sin hacer global $fichero, por otro lado, $_FILES si es una "superglobal" que está disponible ó se puede acceder a ella durante y/ó en cualquier parte del script, y según leí (esto no lo tenía en cuenta) $_FILES esta disponible desde la versión 4.1.0 por lo que $HTTP_POST_FILES quedo completamente "nulled" en esas versiones.

Tomando de siempre de ejemplo en este caso el siguiente uploader:

Código: html5

<form action="subir.php" method="post" enctype="multipart/form-data">
<b>Archivo: </b>
<br>
<input name="fichero" type="file">
<br>
<input type="submit" value="Enviar">
</form>


Comenzemos, las variables príncipales de $_FILES son las siguientes (noten que fichero es el nombre del input type por lo que en $_FILES el primer "valor del array" es el nombre del input, y como mencioné anteriormente, en este caso es fichero:
$_FILES['fichero']['tmp_name'] = Muestra el nombre "temporal" del archivo, puede ser parecido a phpC2.tmp, siempre varian.
$_FILES["fichero"]["name"] = Muestra el nombre original del archivo, en este caso muestra tutorial.txt.
$_FILES["fichero"]["type"] = Muestra el tipo del archivo, en este caso es text/plain pero hay image/jpeg, stream, etc, todo depende si es ejecutable, imagen, texto plano, script, entre otros.
$_FILES["fichero"]["size"] = Muestra el tamaño de archivo en bytes, pueden hacer una operación divisoria de / 1024 para ir convirtiendolo a kb, mb, gb, etc.
Código: php

<?php
echo $_FILES['fichero']['tmp_name']."<br />"; //Es el archivo temporal para subir al servidor
echo $_FILES["fichero"]["name"]."<br />"; //Es el nombre del archivo a subir al servidor
echo $_FILES["fichero"]["type"]."<br />"; //Es el tipo (mime) del archivo a subir al servidor
echo $_FILES["fichero"]["size"]."<br />"; //Es el tamano (en bytes) del archivo a subir al servidor
/*
Nota: Puedes hacer $_FILES["fichero"]["size"] / 1024 para ir en escala de bytes, kb, mb, etc.
Daria como resultado:
C:\WINDOWS\Temp\phpC2.tmp => Temporal
tutorial.txt => Nombre
text/plain => Tipo (mime)
0 => Peso
*/
?>


Como pudieron observar, esas son los valores del array $_FILES que se utilizan para hacer un uploader, solo tiene que coincidir el nombre del input con el del script (en este caso; fichero).

Para hacer la "copia" ó mejor dicho "mover" el archivo al lugar definitivo en donde se almacenará el fichero, se utiliza la función move_uploaded_file(); creo que el nombre lo dice todo.
move_uploaded_file() recibe dos parámetros, el primero es el nombre temporal del archivo a subir, y el segundo es en donde se almacenará, pueden notar que tengo una variable llamada $path que es donde indico a que carpeta subiré los archivos.

Ejemplo:

Código: php

<?php
$path = "files/";
$temporal = $_FILES['fichero']['tmp_name'];
$archivo = basename($_FILES["fichero"]["name"]);
if( (move_uploaded_file($temporal,$path.$archivo))){
echo "Archivo subido correctamente.";
}else{
echo "Hubo un error en la carga del archivo.";
}
?>


Aqui pueden utilizar simplemente $_FILES["fichero"]["name"] sin necesidad del basename ya que la funcion basename() solo vota el nombre de fichero.
-----------------------------------------------------------
Copiar un archivo
-----------------------------------------------------------
Para copiar un archivo se utiliza la función copy() que recibe dos parámetros, el fichero original y la ruta a donde se copiará, ejemplo (Tomando de ejemplo el archivo tutorial.txt que anteriormente subimos):
Código: php

<?php
$path = "files/";
$archivo = basename($_FILES["fichero"]["name"]);
copy($path.$archivo, $path."tutorial_copia.txt");
/*
Daria:
files/tutorial_copia.txt
*/
?>


Recuerden que para copiar un archivo se necesita "determinar" el directorio en donde se encuentra el archivo, inclusive se puede copiar de un directorio a otro.
-----------------------------------------------------------
Comprobar si un fichero/directorio existe
-----------------------------------------------------------
Esto les servirá muchos a aquellos que tengan su modulación digamos "index.php?page=home.php", que prácticamente se incluye la página que se obtiene por get y si no la filtran son vulnerables a RFI/LFI, si no tiene modulación igual funciona, existe una función llamada file_exists() que comprueba la existencia de un fichero, tiene un parámetros que por lógica deben suponer que se trata del archivo, en este caso comprobarémos la existencia del archivo "tutorial_copia.txt".
Código: php

<?php
if (file_exists("./files/tutorial_copia.txt")){
echo "Si existe";
}else{
echo "No existe";
}
/*
Devolveria:
Si existe, pero si cambiamos tutorial_copia por loquesea.txt tiraria no existe porque en este caso no tenemos ese fichero en el servidor.
*/
?>


Un ejemplo de la modulación con GET filtrando el archivo (ya que lo mencioné) sería:
Código: php

<?php
$pagina = strip_tags(stripslashes($_GET['page']));
if (file_exists($pagina)){
include ($pagina);
}else{
echo "No intentes bugear, la pagina no existe, se envio un correo al administrador con tu IP";
}
?>

-----------------------------------------------------------
Crear un directorio
-----------------------------------------------------------
Para crear un directorio existe la función mkdir() en donde mk significa make/crear y dir es directory/directorio, para utilizar esta función se necesitan dos parámetros, el nombre del directorio y los permisos que tendrá el directorio.
Código: php

<?php
mkdir("/dir", "0777");
/*
Daria:
path_base/dir/ con permisos de escritura, lectura y ejecucion (0777).
*/
?>


Aquí se puede utilizar la función "file_exists()" para comprobar si existe el directorio, ejemplo:
Código: php

<?php
if (file_exists("./files")){
echo "Si existe";
}else{
mkdir("/files", "0777");
}
/*
Daria:
Si existe el directorio te da un aviso de que existe, si no existe lo crea con permisos de 0777.
*/
?>

-----------------------------------------------------------
Revisar un directorio y contar archivos
-----------------------------------------------------------
Para ello utilizarémos 2 funciones, scandir() y count() , scandir() ocupa un parámetro (el directorio a escanear) y count ocupa igualmente un parámetro, lo que contará:
Código: php

<?php
$directorio = "files/";
$contador = scandir($directorio);
$total = count($contador);
/*
Si hacemos un var_dump() para mostrar todas los valores nos mostraría todos los archivos que existen en el directorio, en este
caso solo existe 1 (tutorial.txt);
*/
?>

Esto puede ser algo fácil al momento de querer saber que archivos estan en una carpeta determinada, pero casi no se utiliza.
-----------------------------------------------------------
Eliminar un archivo/directorio
-----------------------------------------------------------
Para eliminar un archivo se utiliza la función unlink(), y por otro lado, para eliminar un directorio se utiliza la función rmdir(), las dos funciones tienen un solo parámetros que es la dirección del archivo/directorio.
rmdir() solo permite borrar si el directorio esta vacío:

Código: php

<?php
$archivo = "tutorial.txt";
$directorio = "files/";
rmdir($directorio); //En este caso no se eliminaría porque existe tutorial.txt
unlink($directorio.$archivo); //Eliminamos files/tutorial.txt
?>

Entonces, ¿Qué hacer si la carpeta no está vacía pero queremos eliminarla? Fácil, utilizamos la función scandir() y count() y la implementamos con un bucle for:
For: Es un bucle en donde a diferencia de foreach, indicamos el número de "ciclos" que se repetirá:

Código: php

<?php
$directorio = "files/";
$files = scandir($directorio); //Escaneamos el directorio
$num = count($files ); //Contamos el numero de archivos
for ($i=0; $i<=$num; $i++) {
@unlink ($directorio.$files [$i]); //Ponemos un @ al inicio para evitar mostrar error en pantalla.
}
@rmdir ($directorio); //Ponemos un @ al inicio para evitar mostrar error en pantalla.
?>

Que hacemos con el for:
Indicamos que mientras $i sea menor que el número de archivos, $i irá aumentando de uno en uno, prácticamente si el número de archivos es 1, sería $i=0; $i<=1; $i++, para eso es el bucle for, para indicarle cuantas veces se repetirá el ciclo. Entonces como no sabemos el número de archivos, los contamos con count() y se creará un array con el número total de archivos, así que al poner $files[$i] y anteriormente indicando en el bucle for que $i irá aumentando de uno en uno cada vez hasta que llegue al número de archivos, se eliminará de uno por uno los archivos. Despúes se elimina el directorio vacío.
-----------------------------------------------------------
Renombrar un archivo/directorio
-----------------------------------------------------------
Para renombrar un archivo/directorio utilizamos la función rename() en donde solo necesitamos dos parámetro; el nombre original y el nombre a cambiar.
Código: php

<?php
$file = "files/tutorial.txt";
rename ($file , "files/tutoriales_2.txt");
?>

-----------------------------------------------------------
Comprobar permisos de archivo
-----------------------------------------------------------
Para comprobar los permisos de archivo (saber si es ejecutable, etc) utilizarémos tres funciones:
is_writable($archivo); = Comprueba si se puede escribir.
is_readable($archivo); = Comprueba si se puede leer.
is_executable($archivo); = Comprueba si se puede ejecutar.
-----------------------------------------------------------
Archivos de texto
-----------------------------------------------------------
Cabe mencionar que no solo se puede para archivos de texto, si no para html, php, etc, solo explicaré una función y las demás en comentarios porque creo que podrán entender perfectamente sin necesidad de que explique de una por una.
Comenzaré explicando los permisos de archivos.
Citar
'r' Solo lectura, ubicará el puntero al inicio de todo el archivo.
'r+'  Solo lectura y escritura, ubicará el puntero al inicio de todo el archivo.
'w' Solo escritura, si el archivo no existe intentará crearlo.
'w+' Solo escritura y lectura, si el archivo no existe intentará crearlo
'a' Solo escritura, ubicará el puntero al final de todo el archivo y si no existe intentará crearlo.
'a+' Solo escritura y lectura, ubicará el puntero al final de todo el archivo y si no existe intentará crearlo.
'x' Solo escritura, si el archivo ya existe devolverá un FALSE, si no existe intentará crearlo.
'x+' Solo escritura y lectura, si el archivo ya existe devolverá un FALSE, si no existe intentará crearlo.

Ahora, para abrir un archivo se utiliza la función fopen() el cual recibe dos parámetros, el archivo a abrir y los permisos que le darémos, despues viene fwrite() quien igualmente recibe dos parámetros, el fopen y lo que se intentará escribir en el archivo, y finalmente viene fclose() que solo recibe un parámetro a diferencia de los otros dos, solo recibe el fwrite quien ya trae el fopen.
Código: php

<?php
$file = fopen("tutorial.txt", 'a+');
fwrite($file, "Este es un tutorial de PHP hecho por Xt3mP"); //Se puede utilizar fputs() hacen practicamente lo mismo.
fclose($file)
/*
Daria:
tutorial.txt
Este es un tutorial de PHP hecho por Xt3mP
*/
?>


Se pueden hacer saltos de línea pero podrás identificarlas con \n.
-----------------------------------------------------------
Bueno, esto ha sido todo por este tutorial, estoy un poco cansado y necesito fumar, cualquier error que haya tenido ó parecido favor de avisarme para acomodarlo.
Saludos.
Cada vez que me das Karma me motivas