Guardar y recuperar archivo en un campo blob de PostgreSQL con PHP

Al buscar como insertar un archivo en un campo BLOB de PostgreSQL con PHP, no encontré muchos lugares donde expliquen de una manera clara la forma de hacerlo, los sitios en los que encontré son foros, es así que publico este artículo con el fin de aportar un poco a la utilización de este magífico O-RDBMS.

El desarrollo de este script está basado en lo que hizo mi friend Braulio Soncco, en sus artículos explica como insertar y recuperar imágenes en/de un campo BLOB pero utilizando MySQL.

Requerimientos

Para el desarrollo de este script es necesario tener activado la extensión de PostgreSQL en PHP, para lo cual, si se trabaja en linux se tiene que configurar de acuerdo a la distribución que se tiene(normalemente tiene el nombre pgsql.so), en windows es php_pgsql.dll. También es necesario tener configurado el servidor de base de datos para que acepte conexiones TCP/IP.

Desarrollo del script

PostgreSQL dá la posibilidad de almacenar archivos de gran tamaño en columnas tipo oid, bytea y muchos otros, este script utiliza ambos tipos para insertar el archivo.

El formulario de upload y el script de inserción está en una sola página, con el nombre index.php:

php:
<?php
        include_once "sitedefs.php";
        # Muestra el mensaje de confirmación
        $msg="";
        # Verificamos que el formulario no ha sido enviado aun
        $postback = (isset($_POST["enviar"])) ? true : false;
        # Concexión a la base de datos
        $link = pg_connect("host=$dbhost user=$dbuser password=$dbpwd dbname=$dbname") or die(pg_last_error($link));
        if($postback){   
                # Variables del archivo
                $type = $_FILES["archivo"]["type"];
                $tmp_name = $_FILES["archivo"]["tmp_name"];
                $size = $_FILES["archivo"]["size"];
                $nombre = basename($_FILES["archivo"]["name"]);
                # Contenido del archivo
          $fp = fopen($tmp_name, "rb");
        $buffer = fread($fp, filesize($tmp_name));
                fclose($fp);
                # Descripción de la foto
                $desc = $_POST["desc"];
                $isoid=$_POST['tipo']=='oid'?true:false;
                if(!$isoid){
                        # Escapa el contenido del archivo para ingresarlo como bytea
                        $buffer=pg_escape_bytea($buffer);
                        $sql = "INSERT INTO foo(nombre, descripcion, archivo_bytea, mime, size)
                                                        VALUES ('$nombre', '$desc', '$buffer', '$type', $size)"
;
                }
                else{
                        # Inicia una transacción
                        pg_query($link, "begin");
                        # Crea un objeto blob y retorna el oid
                        $oid=pg_lo_create($link);
                        $sql = "INSERT INTO foo(nombre, descripcion, archivo_oid, mime, size)
                        VALUES ('$nombre', '$desc', $oid, '$type', $size)"
;
                }
                # Ejecuta la sentencia SQL
                pg_query($link, $sql) or die(pg_last_error($link));
                if($isoid){
                        # Abre el objeto blob
                        $blob=pg_lo_open($link,$oid,"w");
                        # Escribe el contenido del archivo
                        pg_lo_write($blob,$buffer);
                        # Cierra el objeto
                        pg_lo_close($blob);
                        # Compromete la transacción
                        pg_query($link, "commit");
                }              
                $msg="Archivo guardado";
        }
        # Lista los archivos subidos a la base de datos
        $sql = "select id, nombre, descripcion, coalesce(archivo_oid,-1) as archivo_oid,
                coalesce(archivo_bytea,'-1') as archivo_bytea from foo;"
;
        $result = pg_query($link, $sql);
        $lista = "";
        if($result){
                while ($row=pg_fetch_array($result)){
                        $lista .= "<tr>";
                        $lista .= "<td>$row[nombre]</td>";
                        $lista .= "<td>$row[descripcion]</td>";
                        $lista .= "<td><a href="download.php?id=$row[id]" title="Intentará mostrar el contenido del archivo">Ver</a> |
                        <a href="
download.php?id=$row[id]&f=1" title="Baja el archivo">Bajar</a></td>";
                        $lista .= "</tr>";
                }
        }
        pg_free_result($result);       
        pg_close($link);
?>
html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es">
<head>
<title>Insertar archivos en un campo blob de PostgreSQL</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
</head>
<body>
<div id="contenedor">
        <div id="cabecera"><h1>Insertar y recuperar un campo BLOB con PHP y PostgreSQL</h1></div>
        <span class="msg"><?=$msg?></span>
        Subir archivo:
        <div id="postform">
                <form name="frmblob" id="frmblob" method="post"
                        enctype="multipart/form-data" action="">

                        <fieldset>
                                <label for="desc" accesskey="e">D<span class="key">e</span>scripción</label><br />
                                <input type="text" id="desc" name="desc" size="55" title="Descripci&oacute;n del archivo" /><br />
                                <label for="archivo" accesskey="r">A<span class="key">r</span>chivo</label><br />
                                <input type="file" id="archivo" name="archivo" title="Archivo a subir" size="40" /><br />
                                <label for="tipo" accesskey="i">T<span class="key">i</span>po</label><br />
                                <select name="tipo" id="tipo" title="Tipo de dato del campo en que se guardar&aacute; el archivo">
                                        <option value="bytea" title="bytea" selected>bytea</option>
                                        <option value="oid" title="oid">oid</option>                   
                                </select><br />
                                <input type="submit" name="enviar" id="enviar" value="Guardar" />
                        </fieldset>
                </form>
        </div>
        <div id="files">
                <table>
                <tr>
                        <th>Nombre</th>
                        <th>Descripción</th>
                        <th>Mostrar</th>
                </tr>
                        <?=$lista?>
                </table>
        </div>
        <div id="pie">
                <a href="http://www.buayacorp.com" title="Programaci&oacute;n y Dise&ntilde;o">BuayaCorp</a> © 2005<br />
                <a href="http://creativecommons.org/licenses/by/2.0/">
                        <img src="ccsomerights.gif" alt="Licencia de Creative Commons" border="0">
                </a>
        </div>
</div>
</body>
</html>

En las primeras líneas lo que se hace es recuperar los datos del archivo que se está subiendo al servidor, luego se guarda el contenido de dicho archivo en un buffer.

A continuación dependiendo del tipo de dato seleccionado en el formulario se asigna la variable $isoid, que indica que se insertará en el campo de tipo oid o no. Las diferencias que se presentan al utilizar estos tipos de datos es para ingresar un registro de tipo bytea es necesario ingresar en el formato correcto (tiene que estar en formato octal, 134 = 92 = contra slash), en cambio para trabajar con oid's es necesario utilizar transacciones y funciones especiales para la escritura de objetos BLOB.

El resto del código es para listar los objetos que ya fueron insertados en la base de datos.

Ahora pasemos al código que se encarga de recuperar el contenido de dichos archivos de la base de datos:

php:
<?
        # El parámetro f=1 indica que se va a forzar a bajar el archivo
        $f=isset($_REQUEST['f'])?$_REQUEST['f']:0;
        # Recupera el id pasado como parámetro
        $id=isset($_REQUEST['id'])?$_REQUEST['id']:0;
        include_once "sitedefs.php";
        # Conexión a la base de datos
        $link = pg_connect("host=$dbhost user=$dbuser password=$dbpwd dbname=$dbname") or die(pg_last_error($link));

        # Recupera el archivo en base al ID
        $sql = "select id, nombre, descripcion, mime, size, coalesce(archivo_oid,-1) as archivo_oid,
        coalesce(archivo_bytea,'-1') as archivo_bytea from foo where id=$id"
;
        $result=pg_query($link, $sql);
        # Si no existe, redirecciona a la página principal
        if(!$result || pg_num_rows($result)<1){
                header("Location: index.php");
                exit();
        }
        # Recupera los atributos del archivo
        $row=pg_fetch_array($result,0);
        pg_free_result($result);
        # Para determinar si archivo a bajar fue ingresado al campo archivo_oid (es de tipo "oid")
        $isoid=false;
        if($row['archivo_bytea']==-1) $isoid=true;
        if($row['archivo_oid']==-1) $isoid=true;
        if($row['archivo_bytea']==-1 && $row['archivo_oid']==-1) die('No existe el archivo para mostrar o bajar');
        if($isoid){
                # Inicia la transacción
                pg_query($link, "begin");
                # Abre el objeto blob
                $file=pg_lo_open($link, $row['archivo_oid'], "r");
        }
        else{
                # Hace el proceso inverso a pg_escape_bytea, para que el archivo esté en su estado original
                $file=pg_unescape_bytea($row['archivo_bytea']);
        }
        # Envío de cabeceras
        header("Cache-control: private");
        header("Content-type: $row[mime]");
        if($f==1)
                header("Content-Disposition: attachment; filename="$row[nombre]"");
        header("Content-length: $row[size]");
        header("Expires: ".gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y")))." GMT");
        header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
        header("Cache-Control: no-cache, must-revalidate");
        header("Pragma: no-cache");
       
        if($isoid){
                # Imprime el contenido del objeto blob
                pg_lo_read_all($file);
                # Cierra el objeto
                pg_lo_close($file);
                # Compromete la transacción
                pg_query($link, "commit");
        }
        else{
                # Imprime el contenido del archivo
                print $file;
        }
        pg_close($link);       
?>

El código se parece al anterior en cuanto al tipo de dato en el que el archivo fué enviado, lo que se hace es recuperar el archivo en base a id seleccionado y determinar qué tipo de dato tiene, luego simplemente se imprime el contenido del archivo que es recuperado de la base de datos.

La estructura de la tabla es la siguiente:

sql:
CREATE TABLE foo(
        id serial PRIMARY KEY NOT NULL,
        nombre varchar(100),
        descripcion varchar(500),
        archivo_bytea bytea,
        archivo_oid oid,
        mime varchar(100),
        size float
);

Elementos Utilizados

119 thoughts on “Guardar y recuperar archivo en un campo blob de PostgreSQL con PHP”

  1. Muy bueno el artículo Alex, soy nuevo en esto y con muchas ganas de aprender y tengo una pregunta, al extraer la foto de la base como puedo hacer que aparezca en la misma página (en el ejemplo sería en index.php) y no aparezca en una nueva?

    muchas gracias

  2. Hola, lo único que tienes que hacer es poner la etiqueta y asignarle el atributo src con la página que muestra la imágen, siguiendo el ejemplo sería de esta forma:

    HTML:
    <img src="download.php?id=$row[id]" title="Algún título" />

    Saludos

  3. Felicidades por tu articulo, es muy bueno, la pregunta es en caso de tener diferentes formatos, esto es, necesito subir diferentes tipos de archivo .doc, .pdf , .xls en fin, cualquier archivo, cual seria el procesimiento para hacerlo , principalmente en bytea, el mismo ? y a la hora de presentarlos en en una nueva pagina como seria ? de antemno

    muchas gracias

  4. Si revisas el script y la estructura de la base de datos (en especial el campo "mime"), verás que se puede subir cualquier tipo de archivo, ahora lo de presentar dichos archivos, no sé exáctamente a que te refieres, ya que los tipos de archivos que se mencionan no se muestran por defecto en los navegadores (a excepción de unos cuantos).

    Saludos

  5. Hola de verdad me esta sirviendo de mucho este codigo, los datos se me guardan bien en la bd pero tengo un problemita al momento de mostrar la foto,me muestra un recuadro con una X roja.. porfavor ayudenme..

  6. Hola Carolina, el ejemplo también muestra ese error? Porque aqui a mi funciona sin ningún problema...

    Saludos

  7. Hola otra vez! ya se ve la imagen pero ahora tengo una pregunta, porque cuando quiero imprimir la imagen con codigo html me muestra puros jeroglificos.. porfavor ayudenme

  8. hola espero que si no es mucha molestia me manden un script dond puedo hacer impresion de algun tipo de documento desde mi pagina, e insertar algunà informacion a un formato ya diseñado....

  9. Hola, sobre la impresión no puedes hacerlo directamente, tienes estas opciones (al menos las que conozco):

    * Exportar y/o crear un documento (pdf, doc, etc), supongo que ya estás en este caso.
    * Usar javascript y CSS para hacer la impresión.

    Recuerda que para ambas opciones necesitas siempre la intervención del usuario.

    Saludos

  10. hola, ese articulo esta muy bueno, y quisiera que me respondieran algo este codigo lo puedo usar para almacenar imagenes, y tambien imagenese en un campo lo?

  11. correcto, pero en el ejemplo utilizado para la creacion de la tabla defienieron el campo archivo_oid como tipo oid y el la tabla que yo uso lo defini como tipo lo, pregunto usando este mismo codigo puedo insertar correctamente la foto en la tabla?

  12. Muchas gracias por este codigo publicado, me ha ayudado mucho, y gracias a ustedes solucione un problema que tenia lo que si no entendi mucho es la diferencia entre bytea y oid, pero con oid me sirve, mas adelante publicare un fragmento del codigo que desarrollaré a partir de este publicado como, por ejemplo mostrar las imagenes bien organizadas bien cheveres. muchas gracias
    Att, Armando de Colombia

  13. Hola Alex!!
    Veras, soy bastante novata aun en php y estoy intentando poder adjuntar un archivo en un formulario pero lo estoy haciendo con mysql y me gustaria saber si este codigo me vale aunq no utilice postgreSQL??
    Es que intentado probarlo y me da errores con la base de datos y imagino sera pq lo hago con mysql.
    Muchas gracias

  14. Hola, quisiera saber como puedo insertar un registro en una base de datos cada cierto tiempo, como una tarea programada, y que se haga automaticamente por ejemplo comparando con la fecha del pc.

    Gracias

  15. Hola a todos.., y muchas gracias a las excelentes personas de admin de esta pagina.
    tengo un problemia con mostrar la imagen en la pagina web.
    Pues no me aparece, solomente la tipica X roja, alguien ayuda.
    Gracias por anticipado

  16. Hola a todos.., y muchas gracias a las excelentes personas de admin de esta pagina.
    tengo un problemia con mostrar la imagen en la pagina web.
    Pues no me aparece, solomente la tipica X roja, alguien ayuda.
    Gracias por anticipado

  17. Hola Felipao,

    Por lo que mencionas posiblemente haya problemas al subir o *codificar* la imagen, estás utilizando el ejemplo tal cual lo descargaste o hiciste modificaciones?

    Saludos

  18. Hice algunas modificaciones, va aun principio me dava el error en el header, Warning: Cannot modify header information - headers already sent by (output started at, medi cuenta por un comment que para resolver el problema tenia q modificar el php.ini lo hice y ahora no memuestra la img, al srcipt no le cambie

  19. Hola,

    Ese error no se soluciona desde el php.ini, tienes que modificar el script para que no haya ninguna salida antes del envío de cabeceras; para corregirlo, simplemente borra cualquier "echo" que encuentres o algún espacio que haya al principio de la página. Otra alternativa para solucionar tu problema es que controles la salida con las funciones que trae PHP para este fin (http://www.php.net/manual/es/ref.outcontrol.php)

    Saludos

  20. Excelente script, pero tengo una pregunta. ¿Cuál método es más recomendado? Tengo entendido que oid esta diseñado para cargar archivos muy grandes mientras que bytea es para archivos más pequeños.

  21. Muchas gracias Elisa.
    Resulta que almacene unos documentos pdf en la base de datos y todo sin problemas, inclusive a la hora de presentarlos o descargarlos no hay problema con firefox, pero con explorer no saca el cuadro de dialogo para descargar o guardar.
    Este es el sitio donde tengo desarrollado dicho algoritmo:
    http://www.proantioquia.org.co/publico/informesgestion.php Si clickeas con firefox todo va bien, pero con explorer no?

  22. Hola
    Muchas Gracias, por la ayuda, resolvi mi problema.
    Buena Onda.
    Mi problema eran los espacios.

  23. Estuve probando según yo éste código solo funciona mostrando imagen por imagen .. y si quisiera mostrar todas las imagenes en miniatura en una lista (galería) .. tendría que hacer algo como lo mencionado anteriormente para cada registro ??

    Otra pregunta .. si quisiera agregar esa imagen a un pdf generado dinamicamente .. cómo le puedo hacer ????

  24. La variable $file del código la podría agregar al código que me genera el pdf ??? Lo he intentado pero no se si es correcto..

  25. Hola Elisa,

    Si quieres mostrar todas las imágenes -asumiendo que estás utilizando el script de la entrada- necesitas de un mínimo de 2 páginas, una que se encargue de entregarte la imágen y otra de listarlas. Para el caso que mencionas, la tarea se facilita si sólo guardas las rutas de los ficheros.

    Para agregar la imagen al pdf va a depender de como funcionan las librerías/funciones con las que generas estos pdf's.

    Saludos
    PS. Disculpa por la demora en responder

  26. Gracias el codigo me funciona de maravilla pero queria hacer una preguntar para poder utilizar el codiga de la descarga de los archvos hacia el cliente, he estado probando el realizarlo como una funcion y al momento de pasar los parametros "$id=isset($_REQUEST['id'])?$_REQUEST['id']:0;", en donde en el ejemplo se pasan mediante un formulario yo los paso mediante una variable de funcion asi "function carga ($id)" al mostrar la foto solo me aparece basura, me gustaria que me ayudaran ya que he tratado de varias maneras y no me ha funcionado.

  27. Hola,

    Sería mejor si muestras un poco de código (envíamelo a alex at buayacorp dot com)

    Saludos

  28. hola, gracias por el script, me esta sirviendo de mucho aunque me da un error en la funcion download:

    Warning: pg_query(): Query failed: ERROR: syntax error at end of input at character 154 in c:\proyecto\download.php on line 12

    Warning: Cannot modify header information - headers already sent by (output started at c:\proyecto\download.php:12) in c:\proyecto\download.php on line 15

    por que puede ser? he mirado la sintaxis y creo q esta bien...

  29. buenas, ya he arreglado eso redefiniendo la variable $sql y $link (no me lo explico...) aunque me siguen sin funcionar la funcion download,

    Parse error: parse error in c:\proyecto\download.php on line 15

    :(

  30. Hola joaquin,

    Debo suponer que modificaste el script para que te mande ese error no?, sería bueno que indiques la versión de PostgreSQL que estás usando y además la consulta SQL que se está ejecutando...

    Saludos

  31. gracias por la respuesta alex,

    Lo modifique con los nombres de los campos de mi base de datos pero ya he logrado que funcione del todo y va perfecto, ademas me ha servido para ir buscando una a una las funciones y ver que hacían. Una cosa que me volvio loco y quizas pueda ayudar a alguien fue que al copiarlo a dreamweaver se quedaron un espacio justo delante del me daban posteriormente errores en los header donde se hace la descarga. Tambien he metido entre parentesis el if de la redireccion a la pagina principal:

    if((!$result)||(pg_num_rows($result)

  32. (continuo que se corto a medias)

    no se si eso ultimo es superfluo pero asi me funciona... De nuevo muchisimas gracias, me ha servido de mucho, sera la base de un proyecto de almacenamiento de ficheros de una empresa. Un saludo!.

  33. Bueno como no entendi bien como enviarte mi codigo aqui te envio solamente lo que modifique que la parte que en vez de recibir el id por un request de formulario yo envio el id en una funcion.

  34. function carga ($identifi)
    {
    # El parámetro f=1 indica que se va a forzar a bajar el archivo
    $f=isset($_REQUEST['f'])?$_REQUEST['f']:0;
    # Recupera el id pasado como parámetro
    #$id=isset($_REQUEST['id'])?$_REQUEST['id']:0;
    $id=isset($identifi)?$identifi:0;
    # Conexión a la base de datos
    #$dbhost = "192.168.100.3";
    #$dbuser = "yo";
    #$dbpwd = "cristian";
    #$dbname = "cristian";
    #$link = pg_connect($condb);
    #$link = pg_connect("host=$dbhost user=$dbuser password=$dbpwd dbname=$dbname") or die(pg_last_error($link));

  35. Tengo una pregunta, existe una forma de descargar la foto a una carpeta temporal del cliente, gracias

  36. Quisiera saber como poder insertar o pegar la firma digital o sello a un archivo pdf. gracias un saludo

  37. Hola, este sitio es muy bueno pero tengo una duda muy grande y espero a que me la resuelvan... Estoy desarrollando una página en PHP con MySQL pero quiero guardar imágenes en mi base de datos para luego mostrarlas en el servidor o web. Pero me dijeron que si quiero guardar una imagen en mi base, esta se llenará pronto y que puede bloquearse cuando sea visitada por los usuarios y accedan a las páginas que muestre la imágenes de la bd. Lo que quiero es lo siguiente por ejemplo: con un file en mi formulario buscar la foto que quiero subir a mi base (a lo cual me aparece toda la ruta por ejemplo: "c:\AppServ\SitioWeb\Imagenes\portada.jpeg") y al momento de guardar en la base de datos, me guarda un nombre raro con extensión .tmp) pero yo quiero que nada mas me guarde el nombre de la imagen "portada" y con otro script en php sacar la imagen de la base de datos y mostrarla.
    Por favor me urge la ayuda.....

  38. Te guarda con ese nombre, porque seguramente le pasas la ruta que te devuelve $_FILES["xxx"]["tmp_name"].

    Saludos

  39. Hola amigo, Estuve probando el ejemplo y me funciona perfectamente, tengo 2 preguntas, quisiera mostrar todas las imagenes en miniatura que tengo almacenadas en una Tabla fotos por ejemplo en una lista tipo galería, como podria hacerlo ??? Y mi otra duda es que si puedo mostrar esas imagenes en un Archivo PDF, o EXCEL ???? Gracias...

  40. El es super bueno, me sirvio casi sin generar errores. Quisiera saber si existe la manera de hacer lo mismo con funciones odbc, porque en un proyecto que trabajo las estamos utilizando, y no seria lo mejor combinar funciones pg porque queremos hacer el codigo generico

  41. Si quieres usar ODBC, imagino que sólo podrías hacer uso de campos typo bytea, no así de la interfaz de objetos largos. Para lo primero, sólo tendrías que utilizar una función que haga el mismo trabajo que pg_escape_bytea

  42. hola, el código funciona bien al mostrar la imagen e el navegador, pero yo tengo una pregunta, como puedo insertar esta imagen que estoy recuperando de mi base (byteandola), sobre otra que estoy generando para poderla imprimir junto con otros datos.....

  43. Hola Marcia, sería bueno que expliques con mayor detalle para ayudarte de mejor manera :). Aquí algunas dudas, a qué te refieres con "sobre otra que estoy generando"? ¿vas a unir las dos imágenes?, ¿como es que piensas imprimir?

  44. hola. Lo primero que hago es generar una imagen en blanco que me sirve como "hoja" ($imagen= imagecreate($alto,$ancho)) sobre esta voy colocando texto e imagenes (.jpeg,.gif) con esto no tengo problema el caso es cuando quiero anexar la fotografia que recupero de la tabla con pg_unescape_bytea y poderla colocarla para que se imprima con el resto. Como genero una imagen (que se muestra en una ventana sola), para imprimirla solo la imprimo directamente del navegador. Espero que me entiendas, porque ya he intentado varias cosas y no he podido hacerlo

  45. Marcia, no sé en realidad cuál es el problema que tienes, no sé si es al mezclar la imagen recuperada de la BD con la que generas en tiempo de ejecución o al querer imprimir "directamente" la imagen.

  46. hola.. si es algo confuso, problema es combinar la imagen recuperada de la base de datos en tiempo de ejecución

  47. hola
    Podrian ayudarme, al momento de mostrar la imagen que recupero de una tabla para convertirla en una imagen de php y poderla combinar con otra me la muestra en blanco y negro, cuando es a color.

    //la recuperación la realizo así

    //Así recupero la imagen, Tquery y consultar son funciones hechas para abrir, consultar etc.. la base de datos
    $busca=new Tquery("select foto from fotos where idimagen='$idimagen' ");
    $busca=$busca->consultar();
    $imag=pg_fetch_rows($busca);

    //si no pongo esta linea el imagecreatefromstring marca que no reconoce el formato
    $imagen=pg_unescape_bytea($imag[0]);

    $foto=imagecreatefromstring($imagen);

    // la coloco sobre la imagen creada (fondo $imagen1, las combino ) con
    $w=imagenx($foto);
    $y=$imageny($foto);
    imagecopy($imagen1,$foto,0,0,0,0,$w,$y) ;

  48. hola, disculpa necesitamos tu ayuda (ya que somos nuevas en esto) necesitamos conectar o enlazar una pagina en php con sus resèctivos datos a la base de datos, es decir, que los datos que se estan ingresando en un registro (ejemplo reg_pc) aparezcan cuando se guarde ese formulario en la base de datos (pc) , para despues poder tener un reporte de los mismo.
    te agradezco de antemano por tu ayuda. Gracias

    PD:especificanos los nombres ( ej. base datos, tabla codigo , etc) para que no nos confundas porfavor

  49. Saludos.
    la pagina me sirvio para guardar la imagen dentro de la base de datos de postgres, y tambien hice que me mostrara una miniatura de la misma...
    Pero deseo es otra cosa adicional, de que forma logro extraer la imagen desde la base de datos, para colocarla en una carpeta del disco duro (ejemplo /tmp), existe alguna forma de hacerlo? Gracias.

  50. Gracias por publicar el Artículo,

    Te comento que lo utilice en las ultimas versiones de PHP 5.2 y postgres 8.2, hice unos cambios pero al final
    todo funcionó;

    Disculpa mi exceso de confianza, queria preguntarte si tu conoces la forma de extraer el file (oid) que esta almacenado, utilizando alguna tecnologia microsoft (OLEDB para postgres) bajo VB 60 o Vb.Net
    te lo agradeceria mucho si me indicaras el sitio web donde pueda encontrar tal información.

    Att.
    Walter Campuzano
    Guayaquil - Ecuador

  51. Hola amigo,

    muy interesante tu articulo, es lo k andava buscando, pero me puedes orientar k va dentro de cada archivo y los nombres k les diste, osea como distibuyes el codigo k ofreces en la pagina, de antemano gracias

  52. Hola a todos. Esta muy interesante el articulo. Lo he implementado para un proyecto utilizando solo el método que trabaja con oid's, y almacena el objeto en la tabla pg_largeobject sin problemas. Al momento de descargar el archivo de la BD, se esta colando un salto de linea al principio de la escritura del archivo, lo que ocasiona que al abrir el documento ocurra un error. No entiendo que ha podido salir mal pues he seguido al pie de la letra las indicaciones del tutorial. Alguno se habra topado con el mismo inconveniente que yo? Aradeceria mucho su ayuda. Saludos Cordiales y gracias de antemano.

  53. Raúl, sin ver el código es difícil intentar adivinar porque puede estar produciéndose el error que comentas :)

    Saludos

  54. Hola Alex, disculpa que no haya incluido el código que esta implementado. Incluyo el mismo a continuación. Gracias nuevamente.

    Código para subir el archivo:

    lang:
      include('smarty_instance.php');
      include('model/bd.php');
      $bd = new bd();
      $oSmarty = new Smarty;
      $postback = (isset($_POST["enviar"])) ? true : false;
      if($postback){
        $link = pg_connect("host=server user=user password=password dbname=DB") or die(pg_last_error($link));
        #------
            # VARIABLES DEL ARCHIVO
            $type = $_FILES["archivo"]["type"];
            $tmp_name = $_FILES["archivo"]["tmp_name"];
            $size = $_FILES["archivo"]["size"];
            $nombre = basename($_FILES["archivo"]["name"]);
            #-----
            # CONTENIDO DEL ARCHIVO
            $fp = fopen($tmp_name, "rb");
            $buffer = fread($fp, filesize($tmp_name));
            fclose($fp);
            #-----
            # DESCRIPCION DEL ARCHIVO
            $desc = $_POST["desc"];
            #-----
            # INICIA LA TRANSACCION
            //pg_query($bd->connection(), "begin");
            pg_query($link, "begin");
            #-----
            # CREA UN OBJETO BLOB Y RETORNA EL OID
            //$oid = pg_lo_create($bd->connection());
            $oid = pg_lo_create($link);
            $sql = "INSERT INTO foo(nombre, descripcion, archivo_oid, mime, size) VALUES ('$nombre', '$desc', $oid, '$type', $size)";
            //pg_query($bd->connection(),$sql);
            pg_query($link,$sql);
            # ABRE EL OBJETO BLOB
            $loid =  $oid;
            //$blob = pg_lo_open($bd->connection(),$loid,"w");
            $blob = pg_lo_open($link,$loid,"w");
            #-----
            # ESCRIBE EL CONTENIDO DEL ARCHIVO
            pg_lo_write($blob,str_replace("\r\n","",$buffer));
            #-----
            # CIERRA EL OBJETO
            pg_lo_close($blob);
            #-----
            # COMPROMETE LA TRANSACCION
            #pg_query($link, "commit");
            //pg_query($bd->connection(), "commit");
        pg_query($link, "commit");
      }
      #-----
     

    Código para descargar el archivo:

    lang:
        include('model/bd.php');
            $bd = new bd();
            $id=isset($_REQUEST['id'])?$_REQUEST['id']:0;
            $sql = "select id, nombre, descripcion, mime, size, coalesce(archivo_oid,-1) as archivo_oid,
            coalesce(archivo_bytea,'-1') as archivo_bytea from foo where id=$id";
            $result = $bd->dbquery($sql);
            while($result->fetchInto($row)){
              $doc = $row;
            }
            pg_query($bd->connection(), "begin");
            $file=pg_lo_open($bd->connection(), $doc[5], "r");
            header("Cache-control: private");
            header("Content-type: $doc[3]");
            header("Content-Disposition: attachment; filename=\"$doc[1]\"");
            header("Content-length: $doc[4]");
            header("Expires: ".gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y")))." GMT");
            header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
            header("Cache-Control: no-cache, must-revalidate");
            header("Pragma: no-cache");
            pg_lo_read_all(str_replace("\r\n","",$file));
            pg_lo_close($file);
            pg_query($bd->connection(), "commit");
            pg_close($bd->connection());   

     

  55. Raúl ¿por qué reemplazas los saltos de línea antes de escribir y al momento de recuperar los contenidos de los archivos?, Si éstos son archivos de texto plano, es razonable hacer eso, caso contrario estarías corrompiendo los mismos.

    Saludos

  56. Alex, gracias por tu pronta respuesta. Trate de reemplazar los saltos de lines antes y despues de escribir el archivo, pues pense que el problema podia resolverlo con eso pero no resulto. De hecho, funciona de igual manera. Carga el archivo en BD y lo descarga, pero cuando lo escribe coloca un salto de linea al principio del mismo, lo que corrompe el archivo al igual que ocurre sin colocar el str_replace.

  57. Haz que el script que estás probando muestre todos los errores, puede que algo de esto esté afectando también (he vuelto a probar el ejemplo y no he podido reproducir el error que comentas).

    Saludos

  58. Es extraño, pues no da ningun error.. al momento de guardar un archivo en BD y descargarlo no se presenta ningun problema y el PHP no genera ningun error o warning. Cuando intento abrir el archivo con la aplicacion correspondiente, se produce el error. Pense que a lo mejor pueda ser un problema de configuración del PostgreSQL. Seguire revisando de todas maneras. Gracias por la ayuda

  59. hola: ¿el download.php no funciona en IExplorer 6... ?
    al menos a mi no me funciona...
    en firefox es de lujo...

    muy buena página

  60. ya subi la imagen con el codigo que muestras pero no he podido bajarla solamente me muestra la direccion de esa imagen:
    dicha imagen se elabora en paint y luego se sube espero y me des la idea de como bajarla gracias:
    atte leonel

  61. que mas hombre, me gustaria saber is este codigo en php que coloco me sirve para almacenar archivos pdf y .doc......me gustaria que me ayudara en ese lo necesito para un proyecto,,,,,,,,
    gracias

  62. ahhh se me olvido decirle que si me hace el favor de explicarme eso de ("en windows es php_pgsql.dll. También es necesario tener configurado el servidor de base de datos para que acepte conexiones TCP/IP.")

    en cuanto a los requerimientoss----como lo configuro----gracias

  63. Hola
    bueno tengo una duda como hago para que pueda mostrar la imagen dentro una tabla, hice la prueba pero no da, no se si alguien puede ayudarme con esto se los agradeceria mucho, la cuestion es que quiero poner la imagen junto con otros campos mas pero no da y la verdad no se cual sea el error

  64. Ahora la pregunta es como poder subir a la base de datos de postgre ficheros mas grandes ya sea de cualquier tipo puede audio o video, que no solo se quede en imagenes que son pequeñas.

    Muy bueno el ejemplo de las imagenes muy ilustrativo very good..

  65. Saludos Amigo tengo un inconveniente al momento de guardar la imagen ya que me guarda el bytea con un '\' adicional ej: \21PN\ y se guarda \\21PN\\ esto hace que la imagen se guarde mal y genera problema al momento de recuperarla

  66. Puedes quitar el \ aplicando stripslashes, imagino que esos caracteres de más aparecen porque tienes activado magic_quotes.

  67. hola..
    quisiera me ayudaran o mejor dicho orientaran. despues de que ya tengo mis imagenes en un campo blob en mysql, ya las puedo visualizar en el nvegador, pero ahora quiero poder mandarlas imprimir.. como lo puedo hacer ¿se utilza javascript? o la opcion es pasar esa imagen a un pdf (he escuchadoque existe una libreria llamada fdpf). . . . el punto es que despues de la consulta de la imagen que quiero pued mandarla a la impresora..., ayuda por favor

  68. Hola muy interesante lo que hiciste y muy util, soy algo nuevo en esto y tengo algunas preguntas, espero ser lo mas puntual posible.

    1.¿Cual es la diferencia en oid y bytea?
    2.De esta consulta no entendiendo para que es el coalesce(archivo_oid,-1)?? me podrias decir para que es¿?¿?

    $sql = "select id, nombre, descripcion, coalesce(archivo_oid,-1) as archivo_oid,
    coalesce(archivo_bytea,'-1') as archivo_bytea from foo;";
    3.¿Por que despues que haces el insert del oid luego haces continuas con este codigo, no enteiendo si el obejeto ya habia sido insertado??
    if($isoid){
    # Abre el objeto blob
    $blob=pg_lo_open($link,$oid,"w");
    # Escribe el contenido del archivo
    pg_lo_write($blob,$buffer);
    # Cierra el objeto
    pg_lo_close($blob);
    # Compromete la transacción
    pg_query($link, "commit");
    }

  69. Para 1 y 3, te sugiero que revises la documentación, ahí se explica qué es cada cosa.

    Sobre el punto 2, no tiene importancia esa sentencia puesto que "sólo sirve" para el ejemplo mostrado.

  70. Hola tengo otra pregunta!!!!

    Tipo de dato Oid de postgre es el equivalente al Blob en mysql?¿??¿ si no es asi cual tipo de dato seria el equivalente al Blob de mysq¿?¿?

  71. Hola bueno tengo un error elegi trabajar solo con bytea , mi problema es que cuando intento descargar el archivo este se descarga sin ningun contenido o no tiene formato y cuando intento verlo la pagina carga en blanco la direccion del archivo donwload

    sabes que puede ocasionar que el archivo le pase eso¿?¿

  72. Holas tengo otra duda como haria si quiero evitar que un archivo mayor de 2 megas sea subido¿?¿?¿?¿

    Como hago para validar eso¿?¿?

  73. Buenas tardes, muy interesantes todos los comentarios. Soy novata en la programación de php y postgres y quisiera saber si me podrían resolver una pregunta. Estoy desarrollando una pagina web dinámica, para lo cual utilizo dreamweaver para la parte gráfica, php para la funcionalidad y postgres para el almacenamiento. Como realizo la conexión a la base de datos desde dreamweaver, para utilizar los formularios de inserción y actualización de datos.
    Gracias.

  74. Excelente todo el codigo, muy buena la programacion, tengo una inquietud, al momento de realizar la consulta a la base de datos podria comparar no el id si no el campo de descripcion?, no se si se pueda lo e intentado pero no me funciona

  75. hola, Alex necesito de tu ayuda. El ejemplo me genera el siguiente error: Forbidden

    You don't have permission to access /Upload/< on this server

    Qué debo hacer para solucionarlo, me imagino que debe ser el tipo de conexión tcp/ip, así como tu mencionas. Lo estoy corriendo sobre Windows necesito una mano, saludos y gracias

  76. En hora buena, por el desarrollo. En estos momentos estoy realizando una aplicación en Python(GUI) este mismo ejemplo lo tendrás disponible.

    Saludos

  77. Hola alex tu ejemplo es muy bueno ya que la documentación sobre este tema es muy poca, yo quisiera adaptar este ejemplo para almacenar vídeo trate de subir un video y se pudo pero tengo problemas a la hora de presentarlo cuando trato de verlo, no se si deba cambiar las cabeceras (headers) o que debo hacer si me pudieras orientar te agradeceria

  78. Hola Alex...y atodos los amigos de este blog. Acabo de descubrir este script y me parece genial, luego de haber buscado por toda la red algo parecido...el problema es que yo estoy usando WAMP como servidor de mis páginas web y, si bien me aparece el formulario para subir archivos, al memento de presionar el botón "Guardar" me aparece el mensaje:

    Forbidden
    You don't have permission to access /ejemblob/< on this server.

    Apache/2.0.59 (Win32) PHP/5.1.6 Server at localhost Port 80

    No pude solucionarlo ni dando permisos a la carpeta donde puse los scripts
    :(, luego descubro que se debe a que el action del formulario dice:
    action=""
    si lo elimino caraga a la base de datos la imagen selecionada, pero no me muestra nada de las mismas en el navegador. Podrían darme alguna mano para poder solucionar este conflicto. Gracias de antemano :)

  79. Hola alex, muy bueno tu articulo y me ha servido mucho, pero tengo una pregunta, se pueden subir dos imagenes?, ojala me puedas ayudar, muchas gracias

  80. hola genial tu pag no se si me puedas ayudar la verdad necesite un archivo me lo adjuntaron por correo elctronico lo baje lo abri directamente pero no lo guarde y trabaje por horas en el al momento que le dije guardar me di cuenta que estaba trabajando en el archivo adjunto es muy grande el trabajo ayudame por favor necesito recuperarlo sisisi

  81. me ayudas no se como usar estas etiquetas que hago disculpame siii te prometo que a la proxima lo hare mejor

  82. hola muy buena pag...en realidad t felicito....yo probe el ejemplo y me funciona perfecto...solo kiero preguntarte como haria con este ejempplo para modificar una imagen que ya esta guardada en la base de datos...xfa si puedes ayudarme t lo agradeceria mucho!!!=)

  83. Hola Alex que tal, mucho gusto de antemano te agradezco por esta ayuda.
    Por favor ayudame con algo, resulta que yo estoy usando wamp server, y la verdad es que no se si funcione con este ejemplo.
    El guardar archivo, si lo hace, el problema es cuando quiero ver o descargar el archivo.
    Solo me muestra la url con el id y una página en blanco.
    No se si debo añadir alguna libreria o algo por el estilo.

    Agradecería me respondas a la brevedad posible.

  84. hola Alex ya me habia funcionado correctamente solo que despues de algun tiempo (2 semanas) lo volvi a correr sin hacerle ninguna modificacion ya no funciono correctamente no marca ningun error en el logerror y aparece bien el recuadro pero lo que era la lista de archivos aparece al inicio del recuadro de esta forma:

    "; $lista .= "$row[nombre]"; $lista .= "$row[descripcion]"; $lista .= "Ver | Bajar"; $lista .= ""; } } pg_free_result($result); pg_close($link); ?>

    ¿sabes que esta pasando? ... gracias

  85. hola de nuevo alex :

    Te comento estoy usando firefox, será que algún componente que se cargara automáticamente en el navegador cuando se cargan las nuevas versiones del firefox, sea el problema, es que no entiendo si funcionaba perfectamente ...... de antemano gracias..

  86. hola, soy nueva en esto, y pues quisiera que me ayudaran a resolver un problemita, lo que pasa es que estoy trabajando en un proyecto de gestion de calidad, y pues dentro de este van unas encuestas, las encuestas tienen muchas preguntas, entonces en la base de datos hice una tabla de preguntas y una tabla de respuestas.
    las preguntas, al momento de abrir el formulario me van a cargar automaticamente, en un orden asignado.
    al lado de las preguntas van unas opciones de respuestas que son "si" o "no", cuando yo cheque una opcion ya sea cualquiera de estas dos, el automaticamente me va a guardar la respuesta en la tabla respuesta en el campo opcion que es de tipo BLOB, en el mismo orden que yo las respondi en el formulario, osea, cuando yo eliga la opcion de la primera pregunta, el automaticamente me la va guardando en la bd y automaticamente me va cargando la siguiente pregunta, y asi sucecivamente hasta llegar hasta la ultima pregunta...

    ese el pequeño problema que tengo, lo quiero es que mi formulario me aga esto.ya que no he podido guardar todas las respuestas en un solo campo, y cargar todas las preguntas que estan en un mismo campo de la base de datos.
    espero me ayuden, es de suma urgencia..
    de antemano muchas gracias. :)

  87. Una duda, sabes si Postgres me permite realizar minería de datos a documentos que cargue en la BD usando tu ejemplo???

    Gracias

  88. Hola,me sirvio de mucho el codigo q has puesto pero mi problema es el siguiente yo lo estoy utilizando para guardar en la base de datos archivos de texto como doc o pdf en tipo bytea pero a la hora de recuperaarlo de la base de datos en el campo lo q viene es esto "Resource id #258" y por lo tanto no me lo descarga,q podria ser?gracias de antemano

  89. Buena tarde.

    Basado en su script realicé unas rutinas para la insersión/descargue de archivos en postgres. Todo resultó bien hasta el descargue, ya que los archivos los baja mal. El tamaño es el correcto, pero al visualizarlos abre codigos extraños. Decidí entonces implementar localmente su script tal cual lo tiene para la descarga y de igual manera funciona parcialmente. Al descargar los archivos se visualizan con pura basura. No se si el problema es que lo sube mal o lo descarga mal....estoy con esa inquietud. Mi versión de postgres es la 9. Consulto a ud si para esta versión se requiere de algun elemento adicional mostrado en su script.

    De antemano, muchas gracias.

  90. Hola amigo, excelente sitio y el codigo esta muy bueno, solo tengo un inconveniente, al momento de que querer ver la imagen, me aparece un pequeño recuadro con un archivo roto, no puedo ver la imagen, y al momento de descargarlo se guarda bien, pero al querer abrirlo el visualizador de imagenes me dice que no se reconoce el formato usado o que debo actualiozar el mismo, no se a que se deba, espero me puedan ayudar.

  91. mi pana tengo un inconveniente sabes que guardo la imagen pero a la hora de recuperarla me da error me dice que no se puede mostrar la imagen por q contiene errores sera que me puedes ayudar?

  92. Hola estoy probrando el codigo y me manda el siguiente error

    Forbidden

    You don't have permission to access /ejemplo-postgresql/< on this server.
    Apache/2.2.8 (Win32) PHP/5.2.10 Server at localhost Port 80

Comments are closed.