←

QR codes como data URI sin file storage en el servidor

Contexto

Para un sistema de referidos necesitaba generar QR codes dinamicos por fraccionamiento -- cada uno con una URL unica. Guardar archivos PNG en disco introduce problemas: limpieza, nombres unicos, permisos de directorio, y en hosting serverless simplemente no hay filesystem persistente.

Lo que aprendi

La libreria qrcode de Python puede renderizar a un buffer en memoria con BytesIO. Desde ahi, se convierte a base64 y se retorna como data URI que el browser renderiza directo en un <img>.

Generacion en memoria

import qrcode
import io
import base64

def generate_qr_code(text, size=10):
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=size,
        border=4
    )
    qr.add_data(text)
    qr.make(fit=True)

    img = qr.make_image(fill_color="black", back_color="white")

    buffer = io.BytesIO()
    img.save(buffer, format='PNG')
    buffer.seek(0)

    img_base64 = base64.b64encode(buffer.getvalue()).decode()
    return f"data:image/png;base64,{img_base64}"

Uso en el template

<img src="{{ qr_image }}" alt="QR de referido" />

El valor de qr_image es algo como data:image/png;base64,iVBORw0KGgo... -- el browser lo interpreta como imagen inline sin hacer ninguna peticion HTTP adicional.

Por que este pattern funciona bien

  1. Cero file storage: no hay archivos temporales que limpiar
  2. Sin endpoints adicionales: no necesitas una ruta /static/qr/xxx.png
  3. Cache-friendly: el data URI viaja con el HTML, asi que si cacheas la pagina cacheas el QR
  4. Compatible con serverless: funciona igual en Lambda, Cloud Run, o un VPS con Gunicorn

Cuando NO usarlo

Si generas QR codes muy grandes (version alta, mucha data) o muchos en una sola pagina, el HTML se infla. En ese caso conviene guardar en Blob storage y servir via CDN. Para un sistema de referidos con 1-3 QR por pagina, el data URI es la solucion mas simple.

Referencia