entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

Como mostrar una imagen desde mysql en base64 a un reporte en FPDF con Python

Hola a todos, hace ya unos días vengo trabajando con PyFPDF para generar reportes, tengo un inconveniente al momento de querer mostrar una imagen que tengo guardada en mi base de datos, esta imagen esta en base64, al querer utilizar el método o función image(), tengo que asignarle una ruta, estuve buscando por varios lugares y hay una solución pero de igual forma debo darle una ruta, el detalle es que la imagen esta en la base de datos, como le digo que ruta buscar, si la idea es que no se descargue nada, sino que el tome el valor almacenado (BD) y lo muestre.
cabe aclarar que la imagen la estoy mostrando desde la cabecera, a continuación pondré una parte de mi código, espero alguien me pueda colaborar y gracias de ante mano...

def load_resource(self, reason, filename):
        if reason == "image":
            if filename.startswith("http://") or filename.startswith("https://"):
                f = BytesIO(urlopen(filename).read())
            elif filename.startswith("data"):
                f = filename.split('base64,')[1]
                f = base64.b64decode(f)
                f = io.BytesIO(f)
            else:
                f = open(filename, "rb")
            return f
        else:
            self.error("Unknown resource loading reason \"%s\"" % reason)

def header(self):
        subtitulo = u'TEXTO PRUEBA'

        company_name = u'{0}'.format(data['empresa'])
        nit1 = preview_data['nit_empresa']

        imagen = None if data['image'] is None \
            else "{0},{1}".format("data:image/*;base64",
                                  ImagesConverter.img_convert_to_base64(data['image'].image))
        # LOGO
        img = miClase.load_resource(self, "image", imagen)
        self.image(img, 1, 0.5, 3.2)
        # self.image('/home/felipemedel/Downloads/logo.png', 1, 0.5, 3.2)
       self.set_font('Arial', 'B', 12)
        self.cell(3.8)
        self.multi_cell(12, 0.5, company_name, 0, 'C')
        self.set_font('Arial', 'B', 10)
        self.cell(19.6, 0.5, '{0}'.format('NIT: {0}'.format('.'.join([str(nit1)[i:i + 3] for i in range(0, len(str(nit1)), 3)]))), 0, 0, 'C')
        self.set_font('Arial', 'B', 12)
        self.ln(0.5)
        self.cell(19.6, 0.5, subtitulo, 0, 0, 'C')
        self.ln(1)

        # PAGINACION -----------------------------------------------------------------------------
        self.set_y(3.2)
        self.set_font('Arial', '', 8)
        # NUMERO DE PAGINA----------------------------------------------
        self.cell(19.8, 0.5, u'Página ' + str(self.page_no()) + ' de {nb}', 0, 0, 'R')
        num = self.page_no()
        self.ln(0.5)
        if num > 1:
            self.ln(0.1)

Esta linea de código, la utilizo para convertir el dato de la imagen de la base de datos en base64 para poder procesarla

imagen = None if data['image'] is None \
            else "{0},{1}".format("data:image/*;base64",
                                  ImagesConverter.img_convert_to_base64(data['image'].image))

1 Respuesta

2votos

FelipeMedel Puntos7400

Bueno, con respecto a este tema, no encontre una solución que me permitiera convertir el dato que recibo de mi base de datos para poder mostrar la imagen, asi que lo hice de una forma un poco mas larga pero que igual me permite manejar las imagenes en buen plan, lo primero que hice fue crear un directorio, donde al consultar un reporte, me permita crear una descarga de la imagen y volverla un archivo fisico, de tal forma que pudiera mostrarlo con facilidad.

Los enlaces que tome como base para desarrollar mi solución, fueron los siguientes:

convertir base64 a image

convertir base64 a imagen

video

ahora bien, una de las cosas que hice ya que mi aplicación, tiene varios clientes, y cada uno de estos tiene su propia imagen, fue lo siguiente:

cree un metodo que me permita consultar, si la imagen existe en el directorio...

@staticmethod
    def search_physical_image_route(nit_cliente):
        """
        :param nit_cliente: object cliente
        :return route tha the image:
        """
        from PIL import Image
        try:
            route = "../aplicacion/app/reportes/imagen_cliente/cliente_{}.png".format(nit_cliente)
            if Image.open(route):
                return route
        except Exception as e:
            if e.strerror == "No such file or directory" or e.strerror == "No existe el archivo o el directorio":
                route = None
            else:
                session.rollback()
                print(e)
                raise InternalServerError(e)
        return route

ahora con el siguiente metodo, lo que hago es convertir la imagen a un estado fisico en el directorio, y retorno un ruta para poder agregarla a mi reporte...

@staticmethod
    def save_physical_image(logo_image, nit_cliente):
        """
        :param image: image the cliente
        :param nit_cliente: code the cliente
        :return booleano: True
        """
        import io
        import base64
        from PIL import Image
        try:
            image = base64.decodebytes(logo_image)
            image = Image.open(io.BytesIO(image))
            image.save("app/reportes/imagen_cliente/cliente_{}.png".format(nit_cliente))
            return True
        except Exception as e:
            error = e.args[0][0:26]  # En caso de que no haya identificado el formato de la imagen esta debe ser byte
            if error == "cannot identify image file":
                image = Image.open(io.BytesIO(logo_image))
                image.save("app/reportes/imagen_cliente/cliente_{}.png".format(nit_cliente))
                return True
            else:
                session.rollback()
                print(e)
                raise InternalServerError(e)
            session.rollback()
            print(e)
            raise InternalServerError(e)

con estos dos metodos, consigo obtener la imagen que se ha guardado en mi base de datos, ahora para usarlo en mi reporte, se hace de la siguiente manera...

cliente = session.query(Cliente).filter(Cliente.name == datos_cliente_name,
                                                Cliente.identificationNumber == datos_cliente_nit).first()

        if cliente is not None:
            route = cliente.search_physical_image_route(cliente.identificationNumber)
            x = 1
        else:
            route = False
            x = 0
        if route and x == 1:
            self.image(route, 1, 0.5, 2.8, 2.8, 'PNG')
        elif dato_image != '' and x == 1:
            cliente.save_physical_image(dato_image, cliente.identificationNumber)
            route = cliente.search_physical_image_route(cliente.identificationNumber)
            self.image(route, 1, 0.5, 2.8, 2.8, 'PNG')
        else:
            pass
            # print("Imagen: No se encontro imagen del cliente.")

dato_image = campo de mi base de datos
cliente = variable u objeto en el que obtengo lo que retorna mi consulta
Cliente = referencial de la tabla cliente de mi base de datos
datos_cliente_name = nombre del cliente que inicio sesion actualmente
datos_cliente_nit = nit del cliente que inicio sesion actualmente

verifico que mi consulta traiga algo, si trae algo entonces verifico si existe el archivo, si existe lo muestro, en caso que no exista, hago el llamado a otro metodo, se crea la imagen y despues se muestra, en caso que ninguna de las dos entonces no muestro ninguna imagen...

Espero sea de ayuda para alguien que lo necesite

1voto

lfmd comentado

es una buena opcion, pero en el caso de que sea una sola imagen, podrias guardar la imagen en un directorio y que se actualice en el momento de que se cambie, asi solo guardas el nombre o la ruta completa de la imagen en la base de datos y listo, te evitas convertir la imagen, en caso de que sea solo una...

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta