روبیکا من : https://rubika.ir/artinkarimian3 سایت من : https://sites.google.com/view/artin-karimian
آموزش ساخت یک سرور با پایتون (سرور فایل)

خب شما یک پوشه میسازید با نام : File server
در این پوشه یک پوشه با نام : server
بعد داخل پوشه server یک فایل پایتونی میسازید .
موارد لازم :
1- پایتون
2- کتابخانه flask
داخل فایل پایتونی با اسم app کد زیر را وارد میکنید
import os
import sqlite3
import secrets
from datetime import datetime, timedelta
from flask import Flask, request, render_template, send_file, redirect, url_for, flash
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.secret_key = "change-this-secret-key"
UPLOAD_FOLDER = "uploads"
DATABASE = "files.db"
MAX_CONTENT_LENGTH = 1024 * 1024 * 1024 # 1 GB
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
app.config["MAX_CONTENT_LENGTH"] = MAX_CONTENT_LENGTH
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
def get_db():
conn = sqlite3.connect(DATABASE)
conn.row_factory = sqlite3.Row
return conn
def init_db():
conn = get_db()
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code TEXT UNIQUE NOT NULL,
original_name TEXT NOT NULL,
stored_path TEXT NOT NULL,
uploaded_at TEXT NOT NULL,
expires_at TEXT NOT NULL,
max_downloads INTEGER NOT NULL,
download_count INTEGER NOT NULL DEFAULT 0
)
""")
conn.commit()
conn.close()
def generate_code(length=8):
alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
return "".join(secrets.choice(alphabet) for _ in range(length))
def unique_code():
conn = get_db()
cursor = conn.cursor()
while True:
code = generate_code()
cursor.execute("SELECT id FROM files WHERE code = ?", (code,))
row = cursor.fetchone()
if not row:
conn.close()
return code
def delete_file_record(file_row):
try:
if os.path.exists(file_row["stored_path"]):
os.remove(file_row["stored_path"])
except Exception:
pass
conn = get_db()
cursor = conn.cursor()
cursor.execute("DELETE FROM files WHERE id = ?", (file_row["id"],))
conn.commit()
conn.close()
@app.route("/")
def home():
return render_template("home.html")
@app.route("/upload-page")
def upload_page():
return render_template("upload.html")
@app.route("/download-page")
def download_page():
return render_template("download.html")
@app.route("/upload", methods=["POST"])
def upload_file():
if "file" not in request.files:
flash("فایلی ارسال نشده است.")
return redirect(url_for("upload_page"))
file = request.files["file"]
if file.filename == "":
flash("هیچ فایلی انتخاب نشده است.")
return redirect(url_for("upload_page"))
filename = secure_filename(file.filename)
if not filename:
flash("نام فایل معتبر نیست.")
return redirect(url_for("upload_page"))
try:
expire_value = int(request.form.get("expire_value", "1"))
expire_unit = request.form.get("expire_unit", "hours")
max_downloads = int(request.form.get("max_downloads", "1"))
except ValueError:
flash("مقادیر وارد شده معتبر نیستند.")
return redirect(url_for("upload_page"))
if expire_value < 1:
flash("مدت اعتبار باید حداقل 1 باشد.")
return redirect(url_for("upload_page"))
if max_downloads < 1:
flash("تعداد دانلود باید حداقل 1 باشد.")
return redirect(url_for("upload_page"))
now = datetime.utcnow()
if expire_unit == "minutes":
expires_at = now + timedelta(minutes=expire_value)
elif expire_unit == "hours":
expires_at = now + timedelta(hours=expire_value)
elif expire_unit == "days":
expires_at = now + timedelta(days=expire_value)
else:
flash("واحد زمان نامعتبر است.")
return redirect(url_for("upload_page"))
code = unique_code()
stored_filename = f"{code}_{filename}"
stored_path = os.path.join(app.config["UPLOAD_FOLDER"], stored_filename)
file.save(stored_path)
conn = get_db()
cursor = conn.cursor()
cursor.execute("""
INSERT INTO files (
code, original_name, stored_path,
uploaded_at, expires_at, max_downloads, download_count
)
VALUES (?, ?, ?, ?, ?, ?, 0)
""", (
code,
filename,
stored_path,
now.isoformat(),
expires_at.isoformat(),
max_downloads
))
conn.commit()
conn.close()
return render_template(
"success.html",
code=code,
expires_at=expires_at.strftime("%Y-%m-%d %H:%M:%S UTC"),
max_downloads=max_downloads
)
@app.route("/download", methods=["POST"])
def download_file():
code = request.form.get("code", "").strip().upper()
if not code:
flash("کد را وارد کنید.")
return redirect(url_for("download_page"))
conn = get_db()
cursor = conn.cursor()
cursor.execute("SELECT * FROM files WHERE code = ?", (code,))
file_row = cursor.fetchone()
if not file_row:
conn.close()
flash("کد نامعتبر است یا فایل پیدا نشد.")
return redirect(url_for("download_page"))
now = datetime.utcnow()
expires_at = datetime.fromisoformat(file_row["expires_at"])
# اگر فایل منقضی شده باشد
if now > expires_at:
conn.close()
delete_file_record(file_row)
flash("اعتبار فایل به پایان رسیده و فایل حذف شد.")
return redirect(url_for("download_page"))
# اگر تعداد دانلود پر شده باشد
if file_row["download_count"] >= file_row["max_downloads"]:
conn.close()
delete_file_record(file_row)
flash("حداکثر تعداد دانلود این فایل تمام شده و فایل حذف شد.")
return redirect(url_for("download_page"))
if not os.path.exists(file_row["stored_path"]):
conn.close()
flash("فایل روی سرور موجود نیست.")
return redirect(url_for("download_page"))
new_count = file_row["download_count"] + 1
cursor.execute(
"UPDATE files SET download_count = ? WHERE id = ?",
(new_count, file_row["id"])
)
conn.commit()
conn.close()
# اگر این آخرین دانلود مجاز بود، بعد از این دانلود حذف شود
response = send_file(
file_row["stored_path"],
as_attachment=True,
download_name=file_row["original_name"]
)
if new_count >= file_row["max_downloads"]:
try:
if os.path.exists(file_row["stored_path"]):
os.remove(file_row["stored_path"])
except Exception:
pass
conn = get_db()
cursor = conn.cursor()
cursor.execute("DELETE FROM files WHERE id = ?", (file_row["id"],))
conn.commit()
conn.close()
return response
if __name__ == "__main__":
init_db()
app.run(host="0.0.0.0", port=5000, debug=True)خب حالا داخل پوشه server یک پوشه با اسم : templates میسازید .
داخل اون پوشه
1- یک فایل میسازید با اسم و پسوند : download.html
کد داخل آن :
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>دانلود فایل</title>
<style>
body {
margin: 0;
font-family: Tahoma, Arial, sans-serif;
background: #f4f6f9;
}
.container {
max-width: 650px;
margin: 50px auto;
background: white;
padding: 30px;
border-radius: 18px;
box-shadow: 0 6px 22px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
color: #222;
}
label {
display: block;
margin-top: 18px;
margin-bottom: 8px;
font-weight: bold;
}
input[type="text"] {
width: 100%;
padding: 12px;
border: 1px solid #bbb;
border-radius: 10px;
box-sizing: border-box;
}
button {
margin-top: 25px;
width: 100%;
padding: 14px;
border: none;
border-radius: 12px;
background: #28a745;
color: white;
font-size: 16px;
cursor: pointer;
}
button:hover {
background: #1f7d34;
}
.back {
display: inline-block;
margin-top: 18px;
text-decoration: none;
color: #007bff;
}
.flash {
background: #ffe3e3;
color: #a40000;
padding: 12px;
border-radius: 10px;
margin-bottom: 15px;
}
</style>
</head>
<body>
<div class="container">
<h1>دانلود فایل</h1>
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="flash">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<form action="/download" method="post">
<label>کد فایل را وارد کنید</label>
<input type="text" name="code" placeholder="مثلاً ABCD1234" required>
<button type="submit">دانلود فایل</button>
</form>
<a class="back" href="/">بازگشت به صفحه اصلی</a>
</div>
</body>
</html>2- یک فایل با نام و پسوند : home.html
داخل آن کد :
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>سرور آپلود فایل</title>
<style>
body {
margin: 0;
font-family: Tahoma, Arial, sans-serif;
background: linear-gradient(135deg, #e3f2fd, #f8f9fa);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.box {
background: white;
width: 420px;
padding: 35px;
border-radius: 18px;
box-shadow: 0 8px 30px rgba(0,0,0,0.12);
text-align: center;
}
h1 {
margin-bottom: 25px;
color: #222;
}
.btn {
display: block;
width: 100%;
margin: 15px 0;
padding: 14px;
text-decoration: none;
color: white;
background: #007bff;
border-radius: 12px;
font-size: 17px;
transition: 0.2s;
}
.btn:hover {
background: #0056b3;
}
.btn.secondary {
background: #28a745;
}
.btn.secondary:hover {
background: #1f7d34;
}
</style>
</head>
<body>
<div class="box">
<h1>سرور آپلود فایل</h1>
<a class="btn" href="/upload-page">ورود به صفحه آپلود</a>
<a class="btn secondary" href="/download-page">ورود به صفحه دانلود</a>
</div>
</body>
</html>3- یک فایل دیگر با نام و پسوند : success.html
داخل آن کد زیر را وارد میکنید :
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>آپلود موفق</title>
<style>
body {
margin: 0;
font-family: Tahoma, Arial, sans-serif;
background: #eef7ee;
}
.container {
max-width: 650px;
margin: 50px auto;
background: white;
padding: 30px;
border-radius: 18px;
box-shadow: 0 6px 22px rgba(0,0,0,0.1);
text-align: center;
}
h1 {
color: #1f7d34;
}
.code-box {
background: #f1f8ff;
border: 2px dashed #007bff;
padding: 20px;
margin: 20px 0;
border-radius: 14px;
font-size: 28px;
font-weight: bold;
letter-spacing: 3px;
color: #007bff;
}
.info {
margin-top: 10px;
color: #333;
line-height: 1.9;
}
.btn {
display: inline-block;
margin-top: 20px;
padding: 12px 20px;
text-decoration: none;
color: white;
background: #007bff;
border-radius: 12px;
}
.btn:hover {
background: #0056b3;
}
</style>
</head>
<body>
<div class="container">
<h1>آپلود با موفقیت انجام شد</h1>
<p>کد مخصوص فایل شما:</p>
<div class="code-box">{{ code }}</div>
<div class="info">
<p>تاریخ انقضا: {{ expires_at }}</p>
<p>حداکثر تعداد دانلود: {{ max_downloads }}</p>
</div>
<a class="btn" href="/">بازگشت به صفحه اصلی</a>
</div>
</body>
</html>4- داخل همان پوشه یک فایل با اسم و پسوند : upload.html
کد زیر را داخل فایل وارد میکنید :
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>آپلود فایل</title>
<style>
body {
margin: 0;
font-family: Tahoma, Arial, sans-serif;
background: #f4f6f9;
}
.container {
max-width: 650px;
margin: 50px auto;
background: white;
padding: 30px;
border-radius: 18px;
box-shadow: 0 6px 22px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
color: #222;
}
label {
display: block;
margin-top: 18px;
margin-bottom: 8px;
font-weight: bold;
}
input[type="file"],
input[type="number"],
select {
width: 100%;
padding: 12px;
border: 1px solid #bbb;
border-radius: 10px;
box-sizing: border-box;
}
button {
margin-top: 25px;
width: 100%;
padding: 14px;
border: none;
border-radius: 12px;
background: #007bff;
color: white;
font-size: 16px;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
.back {
display: inline-block;
margin-top: 18px;
text-decoration: none;
color: #007bff;
}
.flash {
background: #ffe3e3;
color: #a40000;
padding: 12px;
border-radius: 10px;
margin-bottom: 15px;
}
.row {
display: flex;
gap: 12px;
}
.row > div {
flex: 1;
}
</style>
</head>
<body>
<div class="container">
<h1>آپلود فایل</h1>
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="flash">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<form action="/upload" method="post" enctype="multipart/form-data">
<label>انتخاب فایل</label>
<input type="file" name="file" required>
<label>مدت اعتبار فایل</label>
<div class="row">
<div>
<input type="number" name="expire_value" min="1" value="1" required>
</div>
<div>
<select name="expire_unit" required>
<option value="minutes">دقیقه</option>
<option value="hours" selected>ساعت</option>
<option value="days">روز</option>
</select>
</div>
</div>
<label>حذف فایل بعد از چند بار دانلود</label>
<input type="number" name="max_downloads" min="1" value="1" required>
<button type="submit">تأیید و آپلود</button>
</form>
<a class="back" href="/">بازگشت به صفحه اصلی</a>
</div>
</body>
</html>حالا از قسمت بالای پوشه server کلمه cmd جای آدرس مینویسیم و وارد cmd میشیم .
حالا کد :
python app.pyرا ارسال کنید و سرور روشن شد .
حالا اگر به داخل گوگل بروید و آدرس :
وارد سرور میشوید .
برای خاموش کردن صفحه داخل همون cmd باز ، کنترل سی را بگیرید.
ساختار کلی پروژه :
file_server/
│
├── app.py
├── files.db
├── uploads/
└── templates/
├── home.html
├── upload.html
├── download.html
└── success.html
کل پروژه را از لینک زیر دانلود کنید :
https://my.files.ir/drive/s/5oFQElodY5mDvQwLfB84fVy30e6Q9Z:MTQ4MjQxMnxwYQ
رمز : artinkarimian
کانال روبیکا من : https://rubika.ir/artinkarimian3
مطلبی دیگر از این انتشارات
پروژه سوم : تولید کننده رمز عبور قوی
مطلبی دیگر از این انتشارات
ایده پروژه پایتون 2025 | ۱۲ ایده عملی در ۴ حوزه کلیدی
مطلبی دیگر از این انتشارات
ساخت بازی مار در NOTEPAD در ۲ دقیقه