Advertisement
  1. Code
  2. CodeIgniter

Cómo Comprimir y Descomprimir Archivos en CodeIgniter

Scroll to top
Read Time: 15 min

Spanish (Español) translation by Rafael Chavarría (you can also view the original English article)

La primera mitad de este tutorial explica diferentes maneras en las que puedes crear un archivo zip usando las APIs integradas de CodeIgniter. Veremos cómo crear y guardar archivos zip en el servidor y cómo puedes hacerlos disponibles para descarga para los usuarios finales también.

La segunda mitad incluye una discusión de cómo puedes descomprimir el archivo. Para demostrar eso, construiremos una página personalizada que permita a los usuarios subir archivos zip que serán extraídos en el servidor después de una carga exitosa de archivo. Para lograr la funcionalidad deseada, ¡la extensión ZipArchive PHP viene a nuestro rescate!

Antes de que continuemos y realmente nos sumerjamos en cosas de desarrollo, listaré los archivos que vamos a desarrollar a lo largo del curso de este tutorial:

  • application/controllers/Zip.php: Es un archivo controlador que demuestra varias formas en que podrías crear un archivo zip.
  • application/controllers/Unzip.php: Es un archivo controlador que incluye el código usado para descomprimir un archivo cargado por el usuario.
  • application/views/file_upload_form.php: Es un archivo vista que contiene código de formulario de carga de archivo HTML bastante básico.
  • application/views/file_upload_result.php: Es un archivo vista que muestra el resultado de un archivo cargado por el usuario; básicamente te dice si el archivo ha sido descomprimido exitósamente.
  • application/libraries/Extractor.php: Este archivo demuestra el concepto de una librería personalizada en CodeIgniter.

¡Con todo en su lugar, estamos listos para continuar a nuestra siguiente sección!

¿Cómo Comprimir Archivos?

Continúa y crea un archivo application/controllers/Zip.php con los siguientes contenidos.

1
<?php
2
// application/controllers/Zip.php

3
defined('BASEPATH') OR exit('No direct script access allowed');
4
5
class Zip extends CI_Controller {
6
    private function _load_zip_lib()
7
  {
8
		$this->load->library('zip');
9
	}
10
	
11
	private function _archieve_and_download($filename)
12
	{
13
		// create zip file on server

14
		$this->zip->archive(FCPATH.'/uploads/'.$filename);
15
		
16
		// prompt user to download the zip file

17
		$this->zip->download($filename);
18
	}
19
20
	public function data()
21
	{
22
		$this->_load_zip_lib();
23
		
24
		$this->zip->add_data('name.txt', 'Sajal Soni');
25
		$this->zip->add_data('profile.txt', 'Web Developer');
26
		
27
		$this->_archieve_and_download('my_info.zip');
28
	}
29
30
	public function data_array()
31
	{
32
		$this->_load_zip_lib();
33
		
34
		$files = array(
35
				'name.txt' => 'Sajal Soni',
36
				'profile.txt' => 'Web Developer'
37
		);
38
		
39
		$this->zip->add_data($files);
40
		
41
		$this->_archieve_and_download('my_info.zip');
42
	}
43
44
	public function data_with_subdirs()
45
	{
46
		$this->_load_zip_lib();
47
		
48
		$this->zip->add_data('info/name.txt', 'Sajal Soni');
49
		$this->zip->add_data('info/profile.txt', 'Web Developer');
50
		
51
		$this->_archieve_and_download('my_info.zip');
52
	}
53
54
	public function files()
55
	{
56
		$this->_load_zip_lib();
57
		
58
		// pass second argument as TRUE if want to preserve dir structure

59
		$this->zip->read_file(FCPATH.'/uploads/1.jpg');
60
		$this->zip->read_file(FCPATH.'/uploads/2.jpg');
61
		
62
		$this->_archieve_and_download('images.zip');
63
	}
64
	
65
	public function dir()
66
	{
67
		$this->_load_zip_lib();
68
		
69
		// pass second argument as FALSE if want to ignore preceding directories

70
		$this->zip->read_dir(FCPATH.'/uploads/images/');
71
		
72
		$this->_archieve_and_download('dir_images.zip');
73
	}
74
}

Es un archivo controlador bastante estándar con el que ta estás familiarizado. Este contiene varios métodos, y cada uno de ellos te muestra una manera diferente de crear un archivo comprimido.

Además de eso, este proporciona dos métodos privados, _load_zip_lib y _archieve_and_download, que son llamados desde el resto de los métodos. Por supuesto, no necesitas implementar estos métodos, pero solo hemos refactorizado nuestro código de manera que no termines repitiendo el mismo código en otros métodos. Primero recorramos estos métodos.

Aquí está cómo luce el método _load_zip_lib.

1
private function _load_zip_lib()
2
{
3
    $this->load->library('zip');
4
}

Este carga la librería zip integrada del framework CodeIgniter de manera que puedas usar las características de esa librería a través del resto del código. Ahora, puedes acceder a la librería zip con la convención $this->zip.

Después, hay un método _archieve_and_download.

1
private function _archieve_and_download($filename)
2
{
3
    // create zip file on server

4
    $this->zip->archive(FCPATH.'/uploads/'.$filename);
5
        
6
    // prompt user to download the zip file

7
    $this->zip->download($filename);
8
}

Como hemos cargado la librería zip, podemos usar los métodos proporcionados por esta. El método archive te permite crear un archivo zip en la ruta proporcionada como el primer argumento. Por el otro lado, el método de descarga pide al usuario para descarga de archivo.

No te preocupes si te estás preguntando sobre los contenidos de nuestro archivo zip, ya que veremos eso en un momento.

Todo está en lugar, ¡así que estamos listos para continuar!

Tomemos el código del método data. Este método te muestra cómo crear archivos al vuelo y envolverlos en un archivo comprimido.

1
public function data()
2
{
3
    $this->_load_zip_lib();
4
        
5
    $this->zip->add_data('name.txt', 'Sajal Soni');
6
    $this->zip->add_data('profile.txt', 'Web Developer');
7
        
8
    $this->_archieve_and_download('my_info.zip');
9
}

Para comenzar, hemos llamado al método _load_zip_lib que carga la librería zip. Después, ¡hemos usado el método add_data de la clase zip que te permite crear un archivo y llenarlo con contenidos al mismo tiempo! Por supuesto, ¡es agregado al archivo también!

El primer argumento debería ser el nombre del archivo, y el segundo argumento tiene los contenidos que van en el archivo.

Como puedes ver, hemos agregado dos archivos, name.txt y profile.txt, con algunos contenidos de demostración. Finalmente, llamamos _archieve_and_download con my_info.zip como un argumento de ese método. ¿Qué es lo que hace?

  • Esto creará un archivo zip my_info.zip bajo tu directorio de subidas.
  • También pedirá al usuario la descarga de archivo, y el nombre con el cuál será guardado el archivo es my_info.zip.

Así que asegúrate de que has creado un directorio uploads en la raíz de tu sitio. También, hazlo de escritura para el usuario del servidor web. Ahora, ¡continua y ejecuta “http://my-codeingiter-site/zip/data” para ver las cosas en acción!

Si tienes cualquier problema, ¡puedes preguntarme en los comentarios!

Después, está el método data_array.

1
public function data_array()
2
{
3
    $this->_load_zip_lib();
4
    
5
    $files = array(
6
        'name.txt' => 'Sajal Soni',
7
        'profile.txt' => 'Web Developer'
8
    );
9
    
10
    $this->zip->add_data($files);
11
    
12
    $this->_archieve_and_download('my_info.zip');
13
}

Este método es idéntico al último que discutimos, ¡excepto que proporcionamos un arreglo de archivos al método add_data en vez de archivos individuales!

Después, tomemos el código del método data_with_subdirs.

1
public function data_with_subdirs()
2
{
3
    $this->_load_zip_lib();
4
        
5
    $this->zip->add_data('info/name.txt', 'Sajal Soni');
6
    $this->zip->add_data('info/profile.txt', 'Web Developer');
7
        
8
    $this->_archieve_and_download('my_info.zip');
9
}

Solo en caso de que quieras organizar tus archivos dentro de ciertos directorios, el método add_data te permite crearlos también. La salida resultante del método de arriba no será diferente excepto que los archivos name.txt y profile.txt serán colocados en el directorio info.

Aunque el método add_data proporciona una agradable característica que te permite crear archivos al vuelo, más seguido que no necesitarás extraer archivos existentes en el servidor. De cualquier modo, eso es exactamente el tema de nuestro siguiente par de métodos.

Veamos rápidamente cómo luce nuestro siguiente método files. Este creará un zip de archivos bajo el directorio uploads.

1
public function files()
2
{
3
    $this->_load_zip_lib();
4
        
5
    // pass second argument as TRUE if want to preserve dir structure

6
    $this->zip->read_file(FCPATH.'/uploads/1.jpg');
7
    $this->zip->read_file(FCPATH.'/uploads/2.jpg');
8
        
9
    $this->_archieve_and_download('images.zip');
10
}

El propósito del método read_file es leer el archivo existente en el servidor y agregarlo al archivo. Así que como puedes ver, hemos agregado los dos archivos 1.jpg y 2.jpg al archivo. Por supuesto, esos dos archivos deben estar presentes bajo el directorio uploads en la raíz de tu sitio.

Si pasas TRUE como el segundo argumento del método read_file, el archivo zip resultante preserva la estructura de directorio exacta en la que el archivo fue colocado.

¡Intenta ejecutar http://my-codeingiter-site/zip/files y revisa el resultado!

El último método en este segmento es el método dir. Este creará un archivo zip del directorio entero.

1
public function dir()
2
{
3
    $this->_load_zip_lib();
4
        
5
    // pass second argument as FALSE if want to ignore preceding directories

6
    $this->zip->read_dir(FCPATH.'/uploads/images/');
7
        
8
    $this->_archieve_and_download('dir_images.zip');
9
}

Puedes usar el método read_dir si quieres crear un archivo zip de todo el directorio en vez de ciertos archivos. En nuestro ejemplo de arriba, creará un archivo dir_images.zip que contiene todos los archivos bajo el directorio /uploads/images/.

La cosa importante a notar aquí es que toda la estructura de directorio será preservada por defecto en el archivo zip. Pero, si quieres ignorarlo, solo pasa FALSE como el segundo argumento del método read_dir. En ese caso, solo creará un directorio images en el archivo zip.

Así que eso concluye nuestra historia sobre cómo crear un archivo zip usando varios métodos proporcionados por la clase zip integrada.

¿Cómo Descomprimir Archivos?

Desafortunadamente, no hay librería CodeIgniter interna que nos permita descomprimir el archivo zip. Pero la extensión ZipArchive PHP lo hace una brisa, como veremos en un momento.

Crearemos un ejemplo bastante simple que demuestra cómo descomprimir archivos subidos por el usuario.

Continúa y crea un archivo application/controllers/Unzip.php con los siguientes contenidos.

1
<?php
2
// application/controllers/Unzip.php

3
defined('BASEPATH') OR exit('No direct script access allowed');
4
5
class Unzip extends CI_Controller {
6
    public function __construct()
7
	{
8
		parent::__construct();
9
		$this->load->helper(array('form', 'url'));
10
	}
11
12
	public function index()
13
	{
14
		$this->load->view('file_upload_form');
15
	}
16
17
	public function upload()
18
	{
19
		$config['upload_path']          = './uploads/';
20
		$config['allowed_types']        = 'zip';
21
		
22
		$this->load->library('upload', $config);
23
		
24
		if ( ! $this->upload->do_upload('zip_file'))
25
		{
26
			$params = array('error' => $this->upload->display_errors());
27
		}
28
		else
29
		{
30
			$data = array('upload_data' => $this->upload->data());
31
			$full_path = $data['upload_data']['full_path'];
32
			
33
			/**** without library ****/
34
			$zip = new ZipArchive;
35
36
			if ($zip->open($full_path) === TRUE) 
37
			{
38
				$zip->extractTo(FCPATH.'/uploads/');
39
				$zip->close();
40
			}
41
42
			$params = array('success' => 'Extracted successfully!');
43
		}
44
		
45
		$this->load->view('file_upload_result', $params);
46
	}
47
}

Creemos también nuestras plantillas de vista, y después veremos cómo trabajo todo junto.

Crea un archivo de plantilla de vista application/views/file_upload_form.php con los siguientes contenidos.

1
<?php
2
// application/views/file_upload_form.php

3
defined('BASEPATH') OR exit('No direct script access allowed');
4
?><!DOCTYPE html>
5
<html lang="en">
6
<head>
7
    <meta charset="utf-8">
8
	<title>Welcome to CodeIgniter</title>
9
10
	<style type="text/css">
11
12
	::selection { background-color: #E13300; color: white; }
13
	::-moz-selection { background-color: #E13300; color: white; }
14
15
	body {
16
		background-color: #fff;
17
		margin: 40px;
18
		font: 13px/20px normal Helvetica, Arial, sans-serif;
19
		color: #4F5155;
20
	}
21
22
	a {
23
		color: #003399;
24
		background-color: transparent;
25
		font-weight: normal;
26
	}
27
28
	h1 {
29
		color: #444;
30
		background-color: transparent;
31
		border-bottom: 1px solid #D0D0D0;
32
		font-size: 19px;
33
		font-weight: normal;
34
		margin: 0 0 14px 0;
35
		padding: 14px 15px 10px 15px;
36
	}
37
38
	code {
39
		font-family: Consolas, Monaco, Courier New, Courier, monospace;
40
		font-size: 12px;
41
		background-color: #f9f9f9;
42
		border: 1px solid #D0D0D0;
43
		color: #002166;
44
		display: block;
45
		margin: 14px 0 14px 0;
46
		padding: 12px 10px 12px 10px;
47
	}
48
49
	#body {
50
		margin: 0 15px 0 15px;
51
	}
52
53
	p.footer {
54
		text-align: right;
55
		font-size: 11px;
56
		border-top: 1px solid #D0D0D0;
57
		line-height: 32px;
58
		padding: 0 10px 0 10px;
59
		margin: 20px 0 0 0;
60
	}
61
62
	#container {
63
		margin: 10px;
64
		border: 1px solid #D0D0D0;
65
		box-shadow: 0 0 8px #D0D0D0;
66
	}
67
	
68
	div {
69
	  padding: 10px;
70
	}
71
	
72
	.error {
73
	  color: #F00;
74
	}
75
	
76
	.success {
77
	  color: #00F;
78
	}
79
	</style>
80
</head>
81
<body>
82
83
<div id="container">
84
	<h1>Upload File</h1>
85
86
	<div id="body">
87
	  <div class="success"><?php if (isset($success)) {echo $success;}?></div>
88
	  <div class="error"><?php if (isset($error)) {echo $error;}?></div>
89
90
		<?php echo form_open_multipart('unzip/upload');?>
91
		  <div>
92
			  <input name="zip_file" type="file"/>
93
			</div>
94
			<div>
95
			  <input type="submit" value="Upload Zip File" />
96
			</div>
97
		</form>
98
	</div>
99
</div>
100
101
</body>
102
</html>

¡Crea un simple formulario de carga de archivo de manera que el usuario pueda cargar el archivo zip! Por favor nota que lo he mantenido al mínimo por el bien de la simplicidad.

Después, creemos un archivo de plantilla de vista application/views/file_upload_result.php.

1
<?php
2
// application/views/file_upload_result.php

3
defined('BASEPATH') OR exit('No direct script access allowed');
4
?><!DOCTYPE html>
5
<html lang="en">
6
<head>
7
    <meta charset="utf-8">
8
	<title>Welcome to CodeIgniter</title>
9
10
	<style type="text/css">
11
12
	::selection { background-color: #E13300; color: white; }
13
	::-moz-selection { background-color: #E13300; color: white; }
14
15
	body {
16
		background-color: #fff;
17
		margin: 40px;
18
		font: 13px/20px normal Helvetica, Arial, sans-serif;
19
		color: #4F5155;
20
	}
21
22
	a {
23
		color: #003399;
24
		background-color: transparent;
25
		font-weight: normal;
26
	}
27
28
	h1 {
29
		color: #444;
30
		background-color: transparent;
31
		border-bottom: 1px solid #D0D0D0;
32
		font-size: 19px;
33
		font-weight: normal;
34
		margin: 0 0 14px 0;
35
		padding: 14px 15px 10px 15px;
36
	}
37
38
	code {
39
		font-family: Consolas, Monaco, Courier New, Courier, monospace;
40
		font-size: 12px;
41
		background-color: #f9f9f9;
42
		border: 1px solid #D0D0D0;
43
		color: #002166;
44
		display: block;
45
		margin: 14px 0 14px 0;
46
		padding: 12px 10px 12px 10px;
47
	}
48
49
	#body {
50
		margin: 0 15px 0 15px;
51
	}
52
53
	p.footer {
54
		text-align: right;
55
		font-size: 11px;
56
		border-top: 1px solid #D0D0D0;
57
		line-height: 32px;
58
		padding: 0 10px 0 10px;
59
		margin: 20px 0 0 0;
60
	}
61
62
	#container {
63
		margin: 10px;
64
		border: 1px solid #D0D0D0;
65
		box-shadow: 0 0 8px #D0D0D0;
66
	}
67
	
68
	div {
69
	  padding: 10px;
70
	}
71
	
72
	.error {
73
	  color: #F00;
74
	}
75
	
76
	.success {
77
	  color: #00F;
78
	}
79
	</style>
80
</head>
81
<body>
82
83
<div id="container">
84
	<h1>Upload File Result</h1>
85
86
	<div id="body">
87
	  <div class="success"><?php if (isset($success)) {echo $success;}?></div>
88
	  <div class="error"><?php if (isset($error)) {echo $error;}?></div>
89
	  <a href="<?php echo site_url('unzip/index'); ?>">&lt;&lt; Back to File Uploader</a>
90
	</div>
91
</div>
92
93
</body>
94
</html>

Una vez que el archivo es subido y extraído, al usuario se le mostrará la plantilla de arriba.

Ahora, regresemos a nuestro controlador y vayamos a través de cada método.

En el constructor de nuestro controlador, hemos cargado los ayudantes CodeIgniter integrados form y url, de manera que podamos usar funciones de ayuda como form_open_multipartsite_url y similares.

Después, echemos un vistazo al método index.

1
public function index()
2
{
3
    $this->load->view('file_upload_form');
4
}

¿Esto necesita alguna explicación? Llama a la vista file_upload_form y genera la página. Así qué, cuando accedes a http://my-codeingiter-site/unzip, debería mostrar un formulario simple de carga de archivo como se muestra abajo.

También, nota que la acción de nuestro formulario es unzip/upload en donde los datos serán  posteados. ¡Hemos usado el ayudante form_open_multipart para generar la etiqueta multiparte de formulario!

Upload PageUpload PageUpload Page

Después, necesitamos implementar el método de acción upload que manejará la carga de archivo y cosas de extracción. Toma el código de eso del controlador Unzip.php.

1
public function upload()
2
{
3
    $config['upload_path']          = './uploads/';
4
    $config['allowed_types']        = 'zip';
5
        
6
    $this->load->library('upload', $config);
7
        
8
    if ( ! $this->upload->do_upload('zip_file'))
9
    {
10
        $params = array('error' => $this->upload->display_errors());
11
    }
12
    else
13
    {
14
        $data = array('upload_data' => $this->upload->data());
15
        $full_path = $data['upload_data']['full_path'];
16
            
17
        $zip = new ZipArchive;
18
19
        if ($zip->open($full_path) === TRUE)
20
        {
21
            $zip->extractTo(FCPATH.'/uploads/');
22
            $zip->close();
23
        }
24
25
        $params = array('success' => 'Extracted successfully!');
26
    }
27
        
28
    $this->load->view('file_upload_result', $params);
29
}

Si estás familiarizado con la carga de archivos en CodeIgniter, el código no debería lucir desconocido para ti. Para aquellos que no están familiarizados, no hay nada de qué preocuparse, ya que las APIs integradas de subida en CodeIgniter lo hacen una brisa.

El siguiente código carga la librería de subida con alguna configuración inicial proporcionada por la variable arreglo $config.

1
$this->load->library('upload', $config);

Lo hemos configurado de manera que el archivo subido será colocado bajo el directorio uploads en la raíz de la aplicación, y al usuario se le permitirá cargar solo archivos zip.

Después, hemos revisado si la carga de archivo ha fallado, y si ese es el caso recogemos un útil mensaje de error y lo asignamos a $params para que podamos mostrarlo en la plantilla.

1
$params = array('error' => $this->upload->display_errors());

En el caso, el archivo es subido exitósamente, así que el siguiente paso es obtener la ruta del archivo del archivo subido.

1
$data = array('upload_data' => $this->upload->data());
2
$full_path = $data['upload_data']['full_path'];

Finalmente, instanciamos un objeto ZipArchive, abrimos nuestro archivo zip, y lo extraemos al directorio uploads.

1
$zip = new ZipArchive;
2
3
if ($zip->open($full_path) === TRUE)
4
{
5
    $zip->extractTo(FCPATH.'/uploads/');
6
    $zip->close();
7
}

¿No fue eso sencillo?

Lo único que nos resta es llamar a la vista file_upload_result, ¡y aquí está cómo debería lucir!

Upload Result PageUpload Result PageUpload Result Page

Así qué, ¡esa es la otra parte de la historia!

Refactoriza el Código de Descompresión a una Librería

Habrás notado que el método upload contiene el código ZipArchive que extrae el archivo subido. ¿Qué si necesitas usar eso código en varios lugares? Podrías estar tentado a copiar y pegar el código según sea necesario.

Ciertamente, hay una mejor manera en la cuál CodeIgniter te permite centralizar código que puede ser usado a través de la aplicación. Podrías crear una librería personalizada.

Continúa y crea un archivo application/libraries/Extractor.php con el siguiente contenido.

1
<?php
2
// application/libraries/Extractor.php

3
class Extractor {
4
    private $CI = NULL;
5
    private $zip = NULL;
6
	
7
    public function __construct($params = array())
8
    {
9
        $this->CI =& get_instance();
10
        $this->zip = new ZipArchive;
11
    }
12
	
13
    public function extract($source_file, $dest_dir)
14
    {
15
        if ($this->zip->open($source_file) === TRUE) 
16
		{
17
			$this->zip->extractTo($dest_dir);
18
			$this->zip->close();
19
        }
20
    }
21
}

Ahora, continúa y reemplaza el método upload en tu controlador Unzip.php con el siguiente.

1
public function upload()
2
{
3
    $config['upload_path']          = './uploads/';
4
    $config['allowed_types']        = 'zip';
5
        
6
    $this->load->library('upload', $config);
7
        
8
    if ( ! $this->upload->do_upload('zip_file'))
9
    {
10
        $params = array('error' => $this->upload->display_errors());
11
    }
12
    else
13
    {
14
        $data = array('upload_data' => $this->upload->data());
15
        $full_path = $data['upload_data']['full_path'];
16
17
        $this->load->library('extractor');
18
        $this->extractor->extract($full_path, FCPATH.'/uploads/');
19
        $params = array('success' => 'Extracted successfully!');
20
    }
21
        
22
    $this->load->view('file_upload_result', $params);
23
}

Como puedes ver, ¡hemos cargado nuestra librería personalizada y le hemos usado para extraer los contenidos!

1
$this->load->library('extractor');
2
$this->extractor->extract($full_path, FCPATH.'/uploads/');

Bastante genial, ¿no?

Y sí, ese es el final de este artículo.

Conclusión

Espero que hayas disfrutado este artículo, en el cuál comenzamos a explorar la librería zip principal del framework CodeIgniter y diferentes formas en que puedes crear un archivo zip. En la segunda parte, expliqué cómo puedes descomprimir archivos subidos por el usuario usando la extensión ZipArchive PHP.

En el proceso, también tengo una oportunidad de convertir nuestro código a una librería personalizada de CodeIgniter, y eso es la cereza del pastel, ¡diría yo!

Déjame saber si tienes preguntas y sugerencias que podrías hacer usando la sección de abajo.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.