Spaces:
Sleeping
Sleeping
import streamlit as st | |
from pathlib import Path | |
from datetime import datetime | |
import zipfile | |
from PIL import Image | |
import time | |
# Page configuration | |
st.set_page_config( | |
page_title="مدیریت فایل", | |
page_icon="📂", | |
layout="wide", | |
initial_sidebar_state="expanded" | |
) | |
# Custom CSS with Farsi font and modern theme | |
st.markdown(""" | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap'); | |
* { | |
font-family: 'Vazirmatn', sans-serif; | |
} | |
.main { | |
background-color: #f0f2f6; | |
} | |
.stButton>button { | |
width: 100%; | |
border-radius: 10px; | |
background-color: #4c78af; | |
color: white; | |
border: none; | |
padding: 0.5rem 1rem; | |
margin: 0.25rem 0; | |
transition: all 0.3s ease; | |
} | |
.stButton>button:hover { | |
background-color: #3a5d8f; | |
box-shadow: 0 4px 8px rgba(0,0,0,0.1); | |
} | |
.uploadedFile { | |
border: 2px dashed #4c78af; | |
border-radius: 10px; | |
padding: 1rem; | |
margin: 1rem 0; | |
} | |
.css-1d391kg { | |
padding: 1rem; | |
border-radius: 10px; | |
background-color: white; | |
box-shadow: 0 2px 4px rgba(0,0,0,0.05); | |
} | |
h1, h2, h3 { | |
color: #1e3d59; | |
} | |
.stProgress .st-bo { | |
background-color: #4c78af; | |
} | |
.stSelectbox, .stMultiSelect { | |
border-radius: 10px; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
# FileManager class for file operations | |
class FileManager: | |
def __init__(self): | |
self.root_path = Path("uploads") | |
self.root_path.mkdir(exist_ok=True) | |
def upload_file(self, file): | |
"""آپلود فایل با نمایش نوار پیشرفت""" | |
progress_text = st.empty() | |
progress_bar = st.progress(0) | |
dest_path = self.root_path / file.name | |
with open(dest_path, "wb") as f: | |
total_size = file.size | |
chunk_size = 1024 | |
bytes_read = 0 | |
while bytes_read < total_size: | |
data = file.read(chunk_size) | |
f.write(data) | |
bytes_read += len(data) | |
progress = bytes_read / total_size | |
progress_bar.progress(progress) | |
progress_text.text(f"در حال آپلود... {int(progress * 100)}%") | |
progress_text.empty() | |
progress_bar.empty() | |
return f"فایل '{file.name}' با موفقیت آپلود شد!" | |
def list_files(self, file_type=None): | |
"""لیست فایلها با امکان فیلتر بر اساس نوع فایل""" | |
files = [ | |
f.name for f in self.root_path.iterdir() | |
if f.is_file() and (not file_type or f.suffix.lower() == file_type.lower()) | |
] | |
return sorted(files) | |
def delete_file(self, filename): | |
"""حذف فایل""" | |
try: | |
path = self.root_path / filename | |
if path.exists(): | |
path.unlink() | |
return "success", f"فایل '{filename}' با موفقیت حذف شد" | |
return "error", f"فایل '{filename}' یافت نشد" | |
except Exception as e: | |
return "error", f"خطا در حذف فایل: {str(e)}" | |
def preview_file(self, filename): | |
"""پیشنمایش فایل""" | |
path = self.root_path / filename | |
try: | |
if path.suffix.lower() in ['.jpg', '.jpeg', '.png', '.gif']: | |
return Image.open(path) | |
elif path.suffix.lower() == '.txt': | |
with open(path, "r", encoding="utf-8") as f: | |
return f.read(500) + "\n...(ادامه دارد)" if path.stat().st_size > 500 else f.read() | |
return "پیشنمایش برای این نوع فایل در دسترس نیست" | |
except Exception as e: | |
return f"خطا در نمایش فایل: {str(e)}" | |
def compress_files(self, files): | |
"""فشردهسازی فایلهای انتخاب شده به ZIP""" | |
if not files: | |
return "error", "لطفاً فایلهایی را برای فشردهسازی انتخاب کنید" | |
try: | |
zip_name = f"compressed_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip" | |
zip_path = self.root_path / zip_name | |
progress_text = st.empty() | |
progress_bar = st.progress(0) | |
with zipfile.ZipFile(zip_path, 'w') as zipf: | |
for i, file in enumerate(files, 1): | |
file_path = self.root_path / file | |
zipf.write(file_path, file) | |
progress = i / len(files) | |
progress_bar.progress(progress) | |
progress_text.text(f"در حال فشردهسازی... {int(progress * 100)}%") | |
progress_text.empty() | |
progress_bar.empty() | |
return "success", f"فایلها با موفقیت فشردهسازی شد: '{zip_name}'" | |
except Exception as e: | |
return "error", f"خطا در فشردهسازی فایلها: {str(e)}" | |
def main(): | |
st.title("📂 مدیریت فایل پیشرفته") | |
file_manager = FileManager() | |
# Layout with two columns | |
col1, col2 = st.columns([2, 1]) | |
with col1: | |
st.subheader("📤 آپلود فایل") | |
uploaded_file = st.file_uploader( | |
"فایل خود را اینجا قرار دهید یا برای انتخاب کلیک کنید", | |
type=["jpg", "jpeg", "png", "gif", "txt"], | |
accept_multiple_files=False | |
) | |
if uploaded_file: | |
result = file_manager.upload_file(uploaded_file) | |
st.success(result) | |
with col2: | |
st.subheader("🔍 فیلتر فایلها") | |
file_type = st.selectbox( | |
"نمایش نوع فایل:", | |
["همه", ".jpg", ".jpeg", ".png", ".gif", ".txt"], | |
index=0 | |
) | |
# List of uploaded files | |
st.subheader("📁 فایلهای آپلود شده") | |
files = file_manager.list_files(None if file_type == "همه" else file_type) | |
if not files: | |
st.info("هنوز فایلی آپلود نشده است") | |
else: | |
for file in files: | |
col1, col2, col3, col4 = st.columns([3, 1, 1, 1]) | |
with col1: | |
if st.button(f"👁️ پیشنمایش {file}"): | |
preview = file_manager.preview_file(file) | |
if isinstance(preview, str): | |
st.text(preview) | |
else: | |
st.image(preview, use_column_width=True) | |
with col2: | |
if st.button(f"🗑️ حذف {file}"): | |
status, message = file_manager.delete_file(file) | |
if status == "success": | |
st.success(message) | |
else: | |
st.error(message) | |
with col3: | |
with open(file_manager.root_path / file, 'rb') as f: | |
st.download_button( | |
label=f"⬇️ دانلود", | |
data=f.read(), | |
file_name=file | |
) | |
# Compression section | |
st.subheader("🗜️ فشردهسازی فایلها") | |
selected_files = st.multiselect( | |
"فایلهای مورد نظر برای فشردهسازی را انتخاب کنید", | |
files | |
) | |
if st.button("📦 فشردهسازی فایلهای انتخاب شده"): | |
if selected_files: | |
status, message = file_manager.compress_files(selected_files) | |
if status == "success": | |
st.success(message) | |
else: | |
st.error(message) | |
else: | |
st.warning("لطفاً فایلهایی برای فشردهسازی انتخاب کنید") | |
if __name__ == "__main__": | |
main() | |