Frasco enviar_archivo()
Aprenderemos, con esta explicación, cómo cargar archivos a la base de datos SQLAlchemy y luego descargar esos archivos de la base de datos en Flask.
Cargue y descargue archivos de la base de datos SQLAlchemy en Flask
Tenemos una aplicación Flask básica con SQLAlchemy y usaremos la plantilla para cargar y descargar un archivo de una base de datos. La función send_file()
nos permite devolver un archivo en lugar de HTML.
from flask import Flask, request, send_file, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db.sqlite3"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
@app.route("/", methods=["GET", "POST"])
def Main_page():
return render_template("index.html")
Creamos un formulario simple dentro del archivo index.html
. Necesitaremos usar enctype="multipart/form-data"
cuando trabajemos con formularios que suben archivos porque si no tenemos eso, no funcionará.
Ahora, lo primero que debemos hacer es crear un modelo, que contendrá información sobre el archivo y los datos del archivo. Llamaremos a esta clase File_Uploader
, que será un modelo de SQLAlchemy.
Este modelo necesitará algunos campos, por lo que creamos una identificación que será la clave principal y, a continuación, agregaremos un File_Name
, que será el nombre del archivo cuando el usuario cargue el archivo a través del formulario. El último es DATOS
, los datos sin procesar del archivo almacenados dentro de la base de datos.
Para estos datos en particular, necesitamos usar un tipo de datos llamado LargeBinary
, que nos permite almacenar datos binarios arbitrarios en la base de datos. Tenga en cuenta que normalmente no almacenamos archivos en la base de datos, pero almacenamos los metadatos en la base de datos.
Podríamos almacenar los archivos en la base de datos si no tenemos muchos archivos, o por limitaciones, queremos mantener todo en la base de datos. Puede enfrentar problemas de rendimiento si combina los datos del archivo con otras columnas en una sola tabla.
Es posible que tenga problemas de rendimiento si esta tabla con los datos del archivo aumenta de tamaño, pero puede hacerlo si lo desea. Es por eso que estamos creando esto.
class File_Uploader(db.Model):
File_ID = db.Column(db.Integer, primary_key=True)
File_Name = db.Column(db.String(50))
DATA = db.Column(db.LargeBinary)
Queremos tomar el archivo del formulario y asegurarnos de que funcione. Dentro de la función Main_page()
, configuraremos la declaración if
para manejar las solicitudes de publicación.
Ahora, obtendremos archivos usando request.files['file']
, los almacenaremos en la variable y le pondremos el nombre Got_File
. Esto obtendrá todos los archivos enviados en la solicitud utilizando la clave particular que enviamos desde el formulario.
if request.method == "POST":
Got_File = request.files["file"]
En el siguiente paso, subiremos esto a la base de datos, que usará el modelo que es File_Uploader
. Pasaremos el Got_File.filename
al campo File_Name
, y luego pasaremos los datos del archivo al campo DATA
.
El Got_File.read()
toma todos los datos binarios del archivo y luego los asigna a donde lo coloquemos. Luego agregaremos una sesión y confirmaremos los datos.
file_upload = File_Uploader(File_Name=Got_File.filename, DATA=Got_File.read())
db.session.add(file_upload)
db.session.commit()
return f"Uploaded: {Got_File.filename}"
Ahora, necesitaremos crear una base de datos y una tabla dentro de la base de datos, por lo que abriremos un shell de Python en el mismo directorio donde se encuentra nuestro archivo app.py
y usaremos los siguientes comandos:
from app import db
db.create_all()
Mirando el directorio raíz, vemos un archivo de base de datos llamado db
. Si arrastramos este archivo dentro del SQLite Viewer, podemos ver que la tabla ha sido creada.
Ahora, ejecutaremos esta aplicación y cargaremos un archivo. Entonces podremos subir los archivos desde el formulario.
Después de ejecutar el servidor, le damos a la ruta desde donde accederemos al formulario para enviar el archivo. Estamos usando estos comandos para configurar la aplicación Flask y ejecutar esta aplicación.
set FLASK_APP='app.py'
flask run
Después de cargar los archivos, podemos ver que los archivos se cargaron correctamente y, si miramos la tabla, tenemos la identificación y el nombre del archivo.
Podemos subir cualquier tipo de archivo; puede ser un mp3, un archivo de película o un archivo de código, lo que sea.
Ahora, crearemos una ruta para descargar el archivo que hemos subido a la base de datos, y tendremos una variable en esta ruta llamada File_ID
. Ahora realizaremos la consulta en la base de datos usando esa identificación y obtendremos datos de la base de datos para esa fila en particular.
@app.route('/download/<File_ID>')
Debemos importar la clase BytesIO
desde el módulo io
. Esto nos permitirá tomar los datos binarios en la base de datos y luego convertirlos a un formato que Flask pueda usar para regenerar el archivo.
Devolveremos el archivo usando la función send_file()
. Luego dentro de la clase BytesIO
, pasamos los datos con la columna correspondiente.
Luego, pasamos el argumento de la palabra clave attachment_filename
porque usaremos un archivo adjunto.
def download(File_ID):
Got_File = File_Uploader.query.filter_by(File_ID=File_ID).first()
return send_file(
BytesIO(Got_File.DATA),
attachment_filename=Got_File.File_Name,
as_attachment=True,
)
Echemos un vistazo a esto. Iremos a la página de descarga y pasaremos el id; cuando llegamos a esta ruta, podemos descargar el archivo.
Código Python completo:
from flask import Flask, request, send_file, render_template
from flask_sqlalchemy import SQLAlchemy
from io import BytesIO
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db.sqlite3"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
class File_Uploader(db.Model):
File_ID = db.Column(db.Integer, primary_key=True)
File_Name = db.Column(db.String(50))
DATA = db.Column(db.LargeBinary)
@app.route("/", methods=["GET", "POST"])
def Main_page():
if request.method == "POST":
Got_File = request.files["file"]
file_upload = File_Uploader(File_Name=Got_File.filename, DATA=Got_File.read())
db.session.add(file_upload)
db.session.commit()
return f"Uploaded: {Got_File.filename}"
return render_template("index.html")
@app.route("/download/<File_ID>")
def download(File_ID):
Got_File = File_Uploader.query.filter_by(File_ID=File_ID).first()
return send_file(
BytesIO(Got_File.DATA),
attachment_filename=Got_File.File_Name,
as_attachment=True,
)
El archivo HTML que usamos dentro de la aplicación Flask:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Uploader </title>
<style>
body {
margin: 0;
}
.center {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
</style>
</head>
<body>
<div class="center">
<form method="POST" action="/" enctype="multipart/form-data">
<input type="file" name="file">
<button>Submit</button>
</form>
</div>
</body>
</html>
Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.
LinkedIn