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:
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))
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…
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
$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…
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 ^^
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
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’.
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…
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 ^^
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?
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?
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 .
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í.