In this tutorial we will build ShareFlow, a simple cloud file sharing platform using Python and Flask.
Users will be able to:
• Register and login
• Upload files
• Generate shareable download links
• Track download counts
• Delete files
By the end you’ll have a mini SaaS file sharing platform similar to Dropbox-style sharing systems.
Project source code:
👉 https://github.com/rogers-cyber/python-tiny-tools/tree/main/77-File-sharing-web-app
- Install Requirements
First install Flask.
pip install flask werkzeug
- Project Structure
Create a simple project structure.
shareflow/
│
├── app.py
├── shareflow.db
└── storage/
The storage folder will hold uploaded files.
- Import Required Libraries
Create app.py and start by importing required modules.
import os
import uuid
import sqlite3
from datetime import datetime
from flask import (
Flask, request, redirect, url_for,
render_template_string, session,
send_from_directory
)
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
What these libraries do
Library Purpose
Flask Web framework
sqlite3 Database
uuid Unique file IDs
werkzeug.security Password hashing
secure_filename Safe file uploads
- Application Configuration
Now define application settings.
APP_NAME = "ShareFlow"
APP_VERSION = "1.0"
UPLOAD_FOLDER = "storage"
DATABASE = "shareflow.db"
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
This section defines:
• Upload directory
• Database file
• App metadata
os.makedirs() ensures the upload folder exists.
- Create the Flask App
Next initialize Flask.
app = Flask(__name__)
app.secret_key = "dev-secret"
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
The secret key is required for sessions.
Sessions allow users to stay logged in.
- Database Helper Function
To simplify database access we create a helper.
def db():
conn = sqlite3.connect(DATABASE)
conn.row_factory = sqlite3.Row
return conn
row_factory allows accessing database rows like:
user["username"]
instead of index positions.
- Initialize the Database
Now we create the required tables.
def init_db():
conn = db()
conn.execute("""
CREATE TABLE IF NOT EXISTS users(
id INTEGER PRIMARY KEY,
username TEXT UNIQUE,
password TEXT
)
""")
Users table
Stores account information.
Files table
Next create a table for uploaded files.
conn.execute("""
CREATE TABLE IF NOT EXISTS files(
id TEXT PRIMARY KEY,
user_id INTEGER,
filename TEXT,
path TEXT,
size INTEGER,
downloads INTEGER,
created TEXT
)
""")
conn.commit()
conn.close()
Each uploaded file tracks:
• owner
• size
• downloads
• upload date
- Detect Current Logged User
We create a helper to check who is logged in.
def current_user():
if "user_id" not in session:
return None
conn = db()
user = conn.execute(
"SELECT * FROM users WHERE id=?",
(session["user_id"],)
).fetchone()
conn.close()
return user
This function is used to protect dashboard routes.
- User Registration
Now let's build the registration page.
@app.route("/register", methods=["GET","POST"])
def register():
if request.method == "POST":
username = request.form["username"]
password = generate_password_hash(request.form["password"])
We hash passwords for security.
Insert the new user:
conn = db()
conn.execute(
"INSERT INTO users(username,password) VALUES(?,?)",
(username,password)
)
conn.commit()
conn.close()
return redirect("/login")
Simple registration form:
return """
<h2>Register</h2>
<form method="post">
<input name="username">
<input name="password" type="password">
<button>Register</button>
</form>
"""
- User Login
Next we create login functionality.
@app.route("/login", methods=["GET","POST"])
def login():
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
Find the user in the database.
conn = db()
user = conn.execute(
"SELECT * FROM users WHERE username=?",
(username,)
).fetchone()
conn.close()
Verify password and login.
if user and check_password_hash(user["password"],password):
session["user_id"] = user["id"]
return redirect("/dashboard")
Login form:
return """
<h2>Login</h2>
<form method="post">
<input name="username">
<input name="password" type="password">
<button>Login</button>
</form>
"""
- Dashboard Page
The dashboard shows uploaded files.
@app.route("/")
@app.route("/dashboard")
def dashboard():
user = current_user()
if not user:
return redirect("/login")
Only logged-in users can access it.
Load user files.
conn = db()
files = conn.execute(
"SELECT * FROM files WHERE user_id=?",
(user["id"],)
).fetchall()
conn.close()
Render the dashboard UI.
return render_template_string(DASHBOARD_HTML, files=files)
- Upload Files
Next we allow users to upload files.
@app.route("/upload", methods=["POST"])
def upload():
user = current_user()
if not user:
return redirect("/login")
Save the uploaded file.
file = request.files["file"]
filename = secure_filename(file.filename)
file_id = str(uuid.uuid4())[:10]
path = os.path.join(
UPLOAD_FOLDER,
file_id + "_" + filename
)
file.save(path)
Store file metadata.
size = os.path.getsize(path)
conn = db()
conn.execute("""
INSERT INTO files
VALUES(?,?,?,?,?,?,?)
""",(
file_id,
user["id"],
filename,
path,
size,
0,
datetime.now()
))
conn.commit()
conn.close()
Redirect back to dashboard.
return redirect("/dashboard")
- Download Files
Each file gets a shareable download link.
@app.route("/f/<file_id>")
def download(file_id):
Find the file.
conn = db()
file = conn.execute(
"SELECT * FROM files WHERE id=?",
(file_id,)
).fetchone()
conn.close()
Increase download count.
conn = db()
conn.execute(
"UPDATE files SET downloads = downloads + 1 WHERE id=?",
(file_id,)
)
conn.commit()
conn.close()
Send the file to the user.
directory = os.path.dirname(file["path"])
filename = os.path.basename(file["path"])
return send_from_directory(directory, filename, as_attachment=True)
- Delete Files
Users can remove uploaded files.
@app.route("/delete/<file_id>")
def delete(file_id):
Find the file.
conn = db()
file = conn.execute(
"SELECT * FROM files WHERE id=?",
(file_id,)
).fetchone()
Delete the file from storage.
if file:
try:
os.remove(file["path"])
except:
pass
Remove it from the database.
conn.execute(
"DELETE FROM files WHERE id=?",
(file_id,)
)
conn.commit()
conn.close()
return redirect("/dashboard")
- Dashboard UI (TailwindCSS)
The dashboard UI uses TailwindCSS for styling.
<script src="https://cdn.tailwindcss.com"></script>
Features:
• Upload form
• File table
• Download links
• Delete buttons
• Download statistics
- Run the Application
Start the server.
if __name__ == "__main__":
init_db()
print("ShareFlow starting...")
print("http://127.0.0.1:5000")
app.run(debug=True)
Run it with:
python app.py
Then open:
http://127.0.0.1:5000
Final Result 🎉
You now have a working file sharing SaaS with:
✔ User accounts
✔ Secure uploads
✔ Shareable links
✔ Download tracking
✔ File deletion
Top comments (0)