Yii Framework Forum: ¿Cómo descargar un archivo que se encuentra en la base de datos? - Yii Framework Forum

Jump to content

  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

¿Cómo descargar un archivo que se encuentra en la base de datos? Descargar un archivo con un enlace desde una vista Rate Topic: -----

#1 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 04 July 2012 - 10:11 AM

Hola a todos, estoy aprendiendo PHP y conociendo Yii y cada vez hago cosas muy buenas pero en esta oportunidad me quedé estacionado y no encuentro la solución a mi problema que es el siguiente:

He guardado un archivo ".txt" en una base de datos a través de un formulario que generó mi modelo en cuestión. Lo que necesito ahora es descargar este archivo para ver su contenido. Exactamente quiero hacerlo mediante un enlace en la vista segun el ID del registro.

Lo que he hecho hasta ahora es esto:

1) Hice esta función en mi controlador para consultar en la base de datos y traerme el contenido que quiero.Por cierto que no comprendo loque significa esta linea de código: (array(':id_tabla1'=>1))

public function Download()
{
$consulta= Yii::app()->db->createCommand()
->select('archivo')
->from('tabla1')
->where('id_tabla1=id_tabla1', array(':id_tabla1'=>1))
->queryAll();


//echo $this->archivo=$fila['archivo'];
return $resultado;
}

2) Para probar que me funcionara llamo a la función dentro del mismo controlador en la accion index para que al ir al index me mostrara la consulta.

public function actionIndex()
{

$objeto=new tabla1;


echo $objeto->Download();//supongo que asi se llama la función y supongo que asi me devolveria el resultado de la consulta...

$dataProvider=new CActiveDataProvider('tabla1');
$this->render('index',array(
'dataProvider'=>$dataProvider,
));
}

3) luego en lo que voy al index me muestra todo lo normal de Yii mas esto: "Array"...

No sé en que estoy fallando he revisado muchos foros y no he dado con la solución además porque casi todo viene en inglés y los que he encontrado lo manejan de otra manera...

agradezco a quien me pueda ayudar! :)
0

#2 User is offline   JCS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 57
  • Joined: 10-January 11
  • Location:Bogotá

Posted 04 July 2012 - 10:41 AM

te recomiendo hacer lo siguiente:

en el archivo modelController.php (cambia model por el nombre de tu modelo) crea una acción llamada 'actionGetTextFile' y agregala en los permisos de acceso del controlador.

public function actionGetTextFile()
{
	$content = ''; // en esta varibale vas a guardar el contenido del archivo que traes de la db
	// header HTML
	header("Cache-Control: public");
	header("Content-Description: File Transfer");
	header("Content-Type: application/octet-stream; ");
	header("Content-Disposition: attachment; filename=archivo.txt");
	header("Content-Transfer-Encoding: binary");
	
	// agregar el contenido
	print_r($content);
}


en donde quieras que se pueda descargar el archivo, creas un link que apunte a 'http://dominio.com/modelo/getTextFile' y cuando hacen click ahi, el navegador empezara a descargar un archivo 'archivo.txt' con el contenido que le asignes

la ruta anterior fue asumiendo que usas el urlManager y ocultas index.php de la ruta de tu aplicacion
0

#3 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 04 July 2012 - 01:58 PM

Gracias por Responder! me funcionó pero:

al sustituir

$content = $this->download();// función de la consulta en el mas simple php (porque no encontré otra forma que me funcionara):

public function Download() 
	{
		$conexion = mysql_connect("miservidor","miusuario","miclave") or die ("Fallo en el establecimiento de la conexión");

		mysql_select_db("prueba_1") or die("Error en la selección de la base de datos");

		$consulta = mysql_query ("SELECT archivo FROM tabla1 WHERE id_tabla1 =id_tabla1") or die ("Error en la consulta SQL");
	
	while( $row = mysql_fetch_array ( $consulta ))
	 {
		
	   
	     echo $row [ "archivo" ];
	   
	}


Cuando hago esto me abre la ventanita para guardar el archivo pero al abrirlo me muestra solo el nombre del archivo y no el contenido!!! será que me estoy equivocando en la consulta? la estaré haciendo incorrectamente? cómo sería?...

Por cierto el archivo puede ser de cualquier extensión...
0

#4 User is offline   JCS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 57
  • Joined: 10-January 11
  • Location:Bogotá

Posted 04 July 2012 - 03:34 PM

jajaja, pues el nombre del archivo lo puedes definir dinamicamente, yo simplemente le puse ese por dar un ejemplo bastante general ^^.

asumo que tienes un modelo Archivo, vamos a ver si esto funciona

public function actionGetTextFile()
{
	$id = $_REQUEST['id']; // Obtener el id de una consulta POST o GET 
	$model = Archivo::model()->findByPk($id); // Trae los datos de un registro especifico del modelo Archivo
	$content = $model->archivo; // Sacamos en valor de 'archivo' de la consulta
	// header HTML
	header("Cache-Control: public");
	header("Content-Description: File Transfer");
	header("Content-Type: application/octet-stream; ");
	header("Content-Disposition: attachment; filename=archivo.txt");
	header("Content-Transfer-Encoding: binary");

	// agregar el contenido
	print_r($content);
}


presento ese $id como $_REQUEST pero pues ya depende de ti como le pases la variable id para que sepa que es lo que debe buscar ^^
0

#5 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 06 July 2012 - 10:15 AM

Hola! no entiendo! jjj tengo en mi controlador hasta ahora esto:

public function Download($ida) 
	{
		$consulta ="SELECT archivo FROM tabla1 WHERE id_tabla1=$ida";
		$comando = Yii::app() -> db -> createCommand($consulta);
		
	    $fila = $comando -> queryRow();
		$archivo=$fila['archivo'];
		
		echo $archivo;
	
	}

Esta función la llamo de mi vista asi:

<?php
 
	$ida=$model->id_tabla1;
	$this->Download($ida); //con esto imprime dentro de la vista sólo el nombre del archivo.Archivo es el campo de tabla1 donde guarde mi doc.
			
echo "<br>";
echo CHtml::link('Descargar 1',array('tabla1/getTextFile')); echo "<br>"; // este es el enlace a la action en el controlador
 ?>


y también esta que me dijiste:

public function actionGetTextFile()
	{
			
			$content = $this->Download($ida);// 
			$extensiones = array("application/msword"=>"doc","application/pdf"=>"pdf","image/jpeg"=>"jpg");
			
			// header HTML
			header("Cache-Control: public");
			header("Content-Description: File Transfer");
			header("Content-Type: application/octet-stream; ");
			header("Content-Disposition: attachment; filename=");
			header("Content-Transfer-Encoding: binary");
			
			//agregar el contenido
			print_r($content);
	}

Luego me sale este error: Undefined variable: ida 
Creo que el problema es cómo pasarle la consulta a la action GetTextFile. Bueno ya viste ccuál es mi consulta de sencilla.pero no comprendo esto que dices que creo que es la solución pero como todo novato no veo!:

 $id = $_REQUEST['id']; // Obtener el id de una consulta POST o GET 
        $model = Archivo::model()->findByPk($id); // Trae los datos de un registro especifico del modelo Archivo
        $content = $model->archivo; // Sacamos en valor de 'archivo' de la consulta

0

#6 User is offline   JCS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 57
  • Joined: 10-January 11
  • Location:Bogotá

Posted 06 July 2012 - 10:51 AM

vamos a analizar las partes del código que pusiste al final del post

/**
 * Esta variable representa el id del registro del cual queremos obtener la informacion,
 * es como la variable $ida que recibes en tu funcion 'Download()', lo mejor es reemplazar
 * $_REQUEST por $_GET
 */
$id = $_REQUEST['id'];
/**
 * Consulta en la base de datos el registro de la tabla con id = $id
 * es como la variable $consulta que tienes en tu función 'Download()',
 * pero este comando hace un 'SELECT *', tu puedes hacer el select de lo que necesites
 */
$model = Archivo::model()->findByPk($id);
/**
 * podemos tratar a $model como un objeto, entonces para acceder a alguno de los campos
 * del registro en la base de datos, lo hacemos con $model->nombreCampo
 * acá asumo que en la base de datos, la columna archivo contiene el texto o lo que
 * sea que debe ir en el archivo, si es una que se llama contenido, entonces será
 * $model->contenido
 */
$content = $model->archivo;


ahora el error que aparece es porque en ningún lado de tu función 'actionGetTextFile()' estas definiendo la variable, solo la estas invocando.

cuando quieras generar el link para descargar, entonces lo que debes hacer es crear un link con javascript para hacer uso de AJAX y le pasas el id como uno de los parámetros de consulta, desde el navegador podrías probarlo accediendo a la ruta: 'http://dominio.com/modelo/getTextFile?id=1'.
0

#7 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 10 July 2012 - 11:20 AM

!!! Me hablaste en chino! jjjj He conseguido en este mismo foro esta manera de hacer el enlace a la acción del controlador:

<?php echo CHtml::link('Link Text',array('controller/action','param1'=>'value1')); ?>


con lo que he sustituido de acuerdo a mi necesidad así:

echo CHtml::link('Link Text',array('tabla1/getTextFile','param1'=>$id));


por supuesto anteriormente he hecho esto en mi vista:

$id=$model->id_tabla1;

para poder utilizar ese "id" y enviarselo.

y la acción del controlador quedo así;

public function actionGetTextFile($id)
	{
		
			$id = $_GET['id'];
			$model = tabla1::model()->findByPk($id);
			$content = $model->archivo;

			// header HTML
			header("Cache-Control: public");
			header("Content-Description: File Transfer");
			header("Content-Type: application/octet-stream; ");
			header("Content-Disposition: attachment; filename=edd.txt");
			header("Content-Transfer-Encoding: binary");
			
			//agregar el contenido
			print_r($content);
	}


¿Será que está bien? porque de otra manera no sé!...

y todavía no me funciona... solo me muestra:

Error 400
Your request is invalid.
0

#8 User is offline   JCS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 57
  • Joined: 10-January 11
  • Location:Bogotá

Posted 10 July 2012 - 11:28 AM

que pasa cuando vas a la siguiente ruta: http://dominio.com/m...etTextFile?id=1 ?????

fíjate que en el link que estas creando le pasas el parametro 'param1', que no es un parametro definido en tu acción, deberías pasarle 'id'

podemos ver el log de errores de Yii o del Servidor??
0

#9 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 10 July 2012 - 03:27 PM

todo lo que me has dicho hasta ahora funciona correctamente, he sustituido esto:

$model = Archivo::model()->findByPk($id);


por esto

 $model = tabla1::model()->findByPk($id);


ya que tabla1 es una tabla de mi db. es decir es un modelo o el modelo que estoy utilizando.

y esto:

$content = $model->archivo; por esto: 


por esto:

$content = $model->archivo; por esto: 


ya que "archivo" es el campo donde guardo el tipo blob que anteriormente se ha guardado.

El resultado final cuando le doy descargar es: me abre el dialogo con el .txt (abrir o guardar...) y al abrir, dentro del .txt me muestra es el nombre del archivo que se encuentra guardado en ese campo mas no me lo abre como debe ser. Es decir, lo que se pretende es que al darle descargar me descargue el archivo como cuando lo guarde. por ejemplo, si guarde un tipo odt o txt o pdf... que me lo retorne nuevamente para guardarlo en un pendrive o simplemente visualizarlo...

¿cómo puedo hacer eso?

View PostJCS, on 10 July 2012 - 11:28 AM, said:

que pasa cuando vas a la siguiente ruta: http://dominio.com/m...etTextFile?id=1 ?????

fíjate que en el link que estas creando le pasas el parametro 'param1', que no es un parametro definido en tu acción, deberías pasarle 'id'

podemos ver el log de errores de Yii o del Servidor??

0

#10 User is offline   JCS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 57
  • Joined: 10-January 11
  • Location:Bogotá

Posted 10 July 2012 - 05:03 PM

pense que en la db guardabas el contenido de un archivo, no el archivo completo ^^, supongo que al guardar el archivo estas guardando tambien el tamaño del archivo, el tipo y el nombre, entonces probemos lo siguiente

<?php
	public function actionGetTextFile($id)
	{
		$id = $_GET['id'];
		$model = tabla1::model()->findByPk($id);
		$content = $model->archivo;
		$size = $model->size;
		$type = $model->type;
		$name = $model->name;

		// header HTML		
		header("Content-length: $size");
		header("Content-type: $type");
		header("Content-Disposition: attachment; filename=$name");

		//agregar el contenido
		echo $content;
	}


y cambia el nombre de la función de actionGetTextFile a uno mas acorde pues no solo se descargaran archivos de texto ^^
0

#11 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 11 July 2012 - 12:57 PM

View PostJCS, on 10 July 2012 - 05:03 PM, said:

pense que en la db guardabas el contenido de un archivo, no el archivo completo ^^, supongo que al guardar el archivo estas guardando tambien el tamaño del archivo, el tipo y el nombre, entonces probemos lo siguiente



Estuve viendo que quizá la forma en que estoy subiendo los archivos puede no ser la correcta. Te explico:

Para el ejemplo de prueba que tengo es una db de 2 tablas. Una de ellas es la tabla1 que tiene 2 campos ("id_tabla1" y "archivo").

El campo "archivo" esta definido como tipo blob

Entonces en el campo "archivo" fue donde subi el archivo como tal a través del formulario create que genera automaticamente yii.
Simplemente en ese formulario le indico "examinar", busco mi archivo y creo.

veo en la base de datos y efectivamente está alli.

aplicando lo último que me dijiste evidentemente me regresa el error: "Property "tabla1.size" is not defined. " porque dentro de la tabla no tengo ese campo.

¿hay alguna forma en yii de extraer tanto el tamaño tipo y contenido de una vez sin agregar esos campos en la tabla?



0

#12 User is offline   JCS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 57
  • Joined: 10-January 11
  • Location:Bogotá

Posted 11 July 2012 - 01:15 PM

no, desafortunadamente debes guardar en algún lado esos valores.

busque un poco en google y acá hay un tutorial, seguro es de mas ayuda de lo que te pueda decir ^^

Uploading files into a MySQL database using PHP
0

#13 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 13 July 2012 - 09:40 AM

Hola amigo buenos días... consegui un ejemplo y corre perfectamente. Entiendo lo que hace y cómo funciona pero no sé cómo aplicarlo a yii pues esta hecho de manera sencilla.

en yii entiendo que el actioncreate te redirecciona al formulario pero después que le das al boton crear pra donde van esos valores de las variables?
0

#14 User is offline   JCS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 57
  • Joined: 10-January 11
  • Location:Bogotá

Posted 13 July 2012 - 10:31 AM

esos valores van para la función actionCreate() de tu controlador
0

#15 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 16 July 2012 - 03:51 PM

Oye, estoy tratando de subir un archivo con esto y no funciona. He hecho un ejemplo del foro y no me funciona:

public function actionCreate()
	{
		$model=new archivo;

		// Uncomment the following line if AJAX validation is needed
		// $this->performAjaxValidation($model);

		if(isset($_POST['archivo']))
		{
			$model->attributes=$_POST['archivo'];
			
			$archivo = CUploadedFile::getInstance($model,'contenido');
			$model->nombre = $archivo->name;
			$model->extension = $archivo->type;


			$fp = fopen($archivo->tempName, 'r');
			$content = fread($fp, filesize($archivo->tempName));
			fclose($fp);

			  $model->contenido = $content;

			
			
			if($model->save())
				$this->redirect(array('view','id'=>$model->id_archivo));
		}

		$this->render('create',array(
			'model'=>$model,
		));
	}


Luego voy al form y modifico "fileField" para cargar el archivo:


<div class="row">
		<?php echo $form->labelEx($model,'contenido'); ?>
		<?php echo $form->fileField($model,'contenido'); ?>
		<?php echo $form->error($model,'contenido'); ?>
	</div>


Después voy al create y cargo el archivo sin llenar nombre ni extension y me muestra este error:

Trying to get property of non-object 


y me señala esta línea:
   $model->nombre = $archivo->name;


Más abajo en el Stack Trace
meseñala esta línea tambien:

Yii::createWebApplication($config)->run();


¿qué será lo que estoy haciendo mal?

Mi db tiene unas sola tabla:"archivo" con los campos: id_archivo, nombre, contenido y extension.
0

#16 User is offline   JCS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 57
  • Joined: 10-January 11
  • Location:Bogotá

Posted 16 July 2012 - 04:08 PM

generaste el modelo, controlador y vistas con Gii??? puedes subir lo que nombre anteriormente en un .zip, asi puedo ver mas facil que puede estar pasando y salir de esto de una vez por todas :P.
0

#17 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 16 July 2012 - 04:18 PM

View PostJCS, on 16 July 2012 - 04:08 PM, said:

generaste el modelo, controlador y vistas con Gii??? puedes subir lo que nombre anteriormente en un .zip, asi puedo ver mas facil que puede estar pasando y salir de esto de una vez por todas :P.


Los modelos los generé por consola. no con el gii gráfico. Te refieres a un zip de la app completa con la db también?
0

#18 User is offline   JCS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 57
  • Joined: 10-January 11
  • Location:Bogotá

Posted 16 July 2012 - 04:22 PM

pues no es necesaria la app completa, solo los archivos relacionados a la subida del archivo y la tabla de la db, no mas ^^
0

#19 User is offline   Eduardo Méndez 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 34
  • Joined: 29-June 12

Posted 17 July 2012 - 08:33 AM

View PostJCS, on 16 July 2012 - 04:22 PM, said:

pues no es necesaria la app completa, solo los archivos relacionados a la subida del archivo y la tabla de la db, no mas ^^



Buenos días hermano, aquí te dejo el sql de la db, el controlador, el modelo y el _form. Gracias...

Attached File(s)


0

#20 User is offline   robregonm 

  • Expert Yii Developer
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 598
  • Joined: 30-July 09
  • Location:Colombia

Posted 17 July 2012 - 10:03 AM

Ahora que hablan de cargar archivo completos en una tabla de la base de datos, lo cual no está mal, pero por rendimiento, se prefiere guardarlos en el sistema de archivos, es decir, en el disco duro, de modo que en la base de datos se guarda la ruta o un identificador para localizarlo.
De todas formas, si es absolutamente necesario almacenarlos en la Base de Datos, entonces, es buena idea guardar información relacionada, con el fin de indexarlos e identificarlos más fácilmente: Fecha Creación, Fecha de subida, Tamaño, Tipo MIME de archivo (la extensión no siempre dice realmente el tipo MIME).... y cosas así.

Saludos y éxitos.
Ricardo Obregón

YiiFramework en Español - http://yiiframework.co/ - http://yiiframeworkenespanol.org/ - Yii Code Generator for Bootstrap
http://obregon.co/ - https://1server.co/
PHP 5.5+, nginx 1.7, MySQL(MariaDB & PerconaDB), PostgreSQL 9, Yii 2, CanJS
Follow me: @robregonm & @obregonco & @1ServerCo.
0

Share this topic:


  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users