subir pagina descomprimir como carpetas php file zip tempdir

php - pagina - Haciendo un directorio temporal para descomprimir un archivo zip en



descomprimir zip en filezilla (7)

Así que primero encontré una publicación de Ron Korving en PHP.net , que luego modifiqué para hacer un poco más seguro (de bucles infinitos, caracteres no válidos y direcciones de padres no grabables) y usar un poco más de entropía.

<?php /** * Creates a random unique temporary directory, with specified parameters, * that does not already exist (like tempnam(), but for dirs). * * Created dir will begin with the specified prefix, followed by random * numbers. * * @link https://php.net/manual/en/function.tempnam.php * * @param string|null $dir Base directory under which to create temp dir. * If null, the default system temp dir (sys_get_temp_dir()) will be * used. * @param string $prefix String with which to prefix created dirs. * @param int $mode Octal file permission mask for the newly-created dir. * Should begin with a 0. * @param int $maxAttempts Maximum attempts before giving up (to prevent * endless loops). * @return string|bool Full path to newly-created dir, or false on failure. */ function tempdir($dir = null, $prefix = ''tmp_'', $mode = 0700, $maxAttempts = 1000) { /* Use the system temp dir by default. */ if (is_null($dir)) { $dir = sys_get_temp_dir(); } /* Trim trailing slashes from $dir. */ $dir = rtrim($dir, DIRECTORY_SEPARATOR); /* If we don''t have permission to create a directory, fail, otherwise we will * be stuck in an endless loop. */ if (!is_dir($dir) || !is_writable($dir)) { return false; } /* Make sure characters in prefix are safe. */ if (strpbrk($prefix, ''///:*?"<>|'') !== false) { return false; } /* Attempt to create a random directory until it works. Abort if we reach * $maxAttempts. Something screwy could be happening with the filesystem * and our loop could otherwise become endless. */ $attempts = 0; do { $path = sprintf(''%s%s%s%s'', $dir, DIRECTORY_SEPARATOR, $prefix, mt_rand(100000, mt_getrandmax())); } while ( !mkdir($path, $mode) && $attempts++ < $maxAttempts ); return $path; } ?>

Por lo tanto, vamos a probarlo:

<?php echo "/n"; $dir1 = tempdir(); echo $dir1, "/n"; var_dump(is_dir($dir1), is_writable($dir1)); var_dump(rmdir($dir1)); echo "/n"; $dir2 = tempdir(''/tmp'', ''stack_''); echo $dir2, "/n"; var_dump(is_dir($dir2), is_writable($dir2)); var_dump(rmdir($dir2)); echo "/n"; $dir3 = tempdir(null, ''stack_''); echo $dir3, "/n"; var_dump(is_dir($dir3), is_writable($dir3)); var_dump(rmdir($dir3)); ?>

Resultado:

/var/folders/v4/647wm24x2ysdjwx6z_f07_kw0000gp/T/tmp_900342820 bool(true) bool(true) bool(true) /tmp/stack_1102047767 bool(true) bool(true) bool(true) /var/folders/v4/647wm24x2ysdjwx6z_f07_kw0000gp/T/stack_638989419 bool(true) bool(true) bool(true)

Tengo un script que comprueba un archivo zip que contiene varios archivos de texto + PDF coincidentes. Quiero desempaquetar, o de alguna manera leer los archivos de texto del archivo zip, y simplemente seleccionar información del archivo de texto para ver si la versión del archivo es correcta.

Estaba buscando en la función tempnam() para encontrar un equivalente para hacer un tempdir, pero tal vez alguien tenga una mejor solución para el problema.

El archivo de índice se ve algo como esto. ( -> es para caracteres TAB). He hecho la función para extraer la versión del archivo de texto y verificar si ya es correcta, solo estoy desempaquetando, tmpdir o alguna otra solución que esté buscando.

1000->filename->file version->program version->customer no->company no->distribution 2000->pagenumber->more info->more info->...


Bastante fácil (en parte lo tomé del manual de PHP):

<?php function tempdir() { $tempfile=tempnam(sys_get_temp_dir(),''''); // you might want to reconsider this line when using this snippet. // it "could" clash with an existing directory and this line will // try to delete the existing one. Handle with caution. if (file_exists($tempfile)) { unlink($tempfile); } mkdir($tempfile); if (is_dir($tempfile)) { return $tempfile; } } /*example*/ echo tempdir(); // returns: /tmp/8e9MLi

Consulte: http://de.php.net/manual/en/function.tempnam.php

Por favor, mire la solución de Will a continuación.

=> Mi respuesta ya no debería ser la respuesta aceptada.


Hay muchas respuestas excesivas a esta pregunta. Una respuesta simple sería:

$tempdir = tempnam(sys_get_temp_dir()) . ''dir''; mkdir($tempdir);

  1. Obtener un nombre de archivo temporal.
  2. Cree el directorio (agregue un sufijo al archivo temporal, para evitar la colisión del nombre del archivo).
  3. Hecho.

La función "mkdir" genera una advertencia si el directorio ya existe, por lo que puede detectarlo usando "@mkdir" y evitar cualquier condición de carrera:

function tempDir($parent = null) { // Prechecks if ($parent === null) { $parent = sys_get_temp_dir(); } $parent = rtrim($parent, ''/''); if (!is_dir($parent) || !is_writeable($parent)) { throw new Exception(sprintf(''Parent directory is not writable: %s'', $parent)); } // Create directory do { $directory = $parent . ''/'' . mt_rand(); $success = @mkdir($directory); } while (!$success); return $directory; }


Otra opción si se ejecuta en Linux con mktemp y el acceso a la función exec es la siguiente:

<?php function tempdir($dir=NULL,$prefix=NULL) { $template = "{$prefix}XXXXXX"; if (($dir) && (is_dir($dir))) { $tmpdir = "--tmpdir=$dir"; } else { $tmpdir = ''--tmpdir='' . sys_get_temp_dir(); } return exec("mktemp -d $tmpdir $template"); } /*example*/ $dir = tempdir(); echo "$dir/n"; rmdir($dir); $dir = tempdir(''/tmp/foo'', ''bar''); echo "$dir/n"; rmdir($dir); // returns: // /tmp/BN4Wcd // /tmp/foo/baruLWFsN (if /tmp/foo exists, /tmp/baruLWFsN otherwise) ?>

Esto evita el problema de carrera potencial (aunque poco probable) anterior y tiene el mismo comportamiento que la función tempnam .


Otra posibilidad es usar el archivo temporal como un tipo de semáforo para garantizar la unicidad del nombre del directorio. Luego, cree un directorio cuyo nombre se base en el nombre del archivo.

define (''TMP_DIR'', ''/tmp''); // sys_get_temp_dir() PHP 5 >= 5.2.1 define (''TMP_DIR_PREFIX'', ''tmpdir_''); define (''TMP_DIR_SUFFIX'', ''.d''); /* ************************************************************************** */ function createTmpDir() { $tmpFile = tempnam(TMP_DIR, TMP_DIR_PREFIX); $tmpDir = $tmpFile.TMP_DIR_SUFFIX; mkdir($tmpDir); return $tmpDir; } function rmTmpDir($tmpDir) { $offsetSuffix = -1 * strlen(TMP_DIR_SUFFIX); assert(strcmp(substr($tmpDir, $offsetSuffix), TMP_DIR_SUFFIX) === 0); $tmpFile = substr($tmpDir, 0, $offsetSuffix); // Removes non-empty directory $command = "rm -rf $tmpDir/"; exec($command); // rmdir($tmpDir); unlink($tmpFile); } /* ************************************************************************** */


Quería agregar un refinamiento a la respuesta de @Mario Mueller, ya que está sujeto a posibles condiciones de carrera, sin embargo, creo que lo siguiente no debería ser:

function tempdir(int $mode = 0700): string { do { $tmp = sys_get_temp_dir() . ''/'' . mt_rand(); } while (!@mkdir($tmp, $mode)); return $tmp; }

Esto funciona porque mkdir devuelve false si ya existe $tmp , lo que hace que el bucle se repita e intente con otro nombre.

Tenga en cuenta también que he agregado el manejo para $mode , con un valor predeterminado que garantiza que el directorio sea accesible solo para el usuario actual, ya que el valor predeterminado de mkdir es 0777 .

Se recomienda encarecidamente que utilice una función de apagado para asegurarse de que el directorio se elimine cuando ya no sea necesario, incluso si su script se cierra por medios inesperados *. Para facilitar esto, la función completa que uso lo hace automáticamente a menos que el argumento $auto_delete esté establecido en false .

// Deletes a non-empty directory function destroydir(string $dir): bool { if (!is_dir($dir)) { return false; } $files = array_diff(scandir($dir), [''.'', ''..'']); foreach ($files as $file) { if (is_dir("$dir/$file")) { destroydir("$dir/$file"); } else { unlink("$dir/$file"); } } return rmdir($dir); } function tempdir(int $mode = 0700, bool $auto_delete = true): string { do { $tmp = sys_get_temp_dir() . ''/'' . mt_rand(); } while (!@mkdir($tmp, $mode)); if ($auto_delete) { register_shutdown_function(function() use ($tmp) { destroydir($tmp); }); } return $tmp; }

Esto significa que, de forma predeterminada, cualquier directorio temporal creado por tempdir() tendrá permisos de 0700 y se eliminará automáticamente (junto con su contenido) cuando finalice la secuencia de comandos.

NOTA : * Puede que este no sea el caso si se elimina la secuencia de comandos, ya que es posible que también deba registrar el registro de un controlador de señales.