attendantelectro commited on
Commit
835a164
·
verified ·
1 Parent(s): 476aad6

Upload 5 files

Browse files
Files changed (5) hide show
  1. README.md +14 -0
  2. api.py +126 -0
  3. app.py +97 -0
  4. packages.txt +2 -3
  5. requirements.txt +4 -4
README.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: File Converter
3
+ sdk: streamlit
4
+ app_file: app.py
5
+ emoji: 🏆
6
+ colorFrom: indigo
7
+ colorTo: gray
8
+ app_port: 7860
9
+ sdk_version: 1.44.1
10
+ pinned: false
11
+ short_description: A space to convert files using various Python libraries.
12
+ ---
13
+
14
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
api.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, send_file
2
+ import os
3
+ import zipfile
4
+ import tempfile
5
+ import shutil
6
+ import rarfile
7
+ from werkzeug.utils import secure_filename
8
+ from pdf2image import convert_from_path
9
+ from PIL import Image
10
+ from moviepy.editor import VideoFileClip
11
+ from pydub import AudioSegment
12
+
13
+ app = Flask(__name__)
14
+ ALLOWED_EXTENSIONS = {'zip', 'rar', 'pdf', 'wav', 'mp4', 'jpg', 'png', 'jpeg'}
15
+
16
+ def allowed_file(filename):
17
+ return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
18
+
19
+ def convert_single_file(input_path):
20
+ base_name, ext = os.path.splitext(input_path)
21
+
22
+ if ext.lower() == '.pdf':
23
+ # PDF تبدیل به WEBP سپس به PDF
24
+ images = convert_from_path(input_path)
25
+ output_path = f"{base_name}_converted.pdf"
26
+ webp_images = []
27
+
28
+ for i, image in enumerate(images):
29
+ webp_path = f"{base_name}_page_{i+1}.webp"
30
+ image.save(webp_path, 'WEBP')
31
+ webp_images.append(Image.open(webp_path))
32
+
33
+ webp_images[0].save(output_path, 'PDF', save_all=True, append_images=webp_images[1:])
34
+ return output_path
35
+
36
+ elif ext.lower() == '.mp4':
37
+ # MP4 تبدیل به MKV
38
+ output_path = f"{base_name}.mkv"
39
+ VideoFileClip(input_path).write_videofile(output_path, codec='libx264')
40
+ return output_path
41
+
42
+ elif ext.lower() == '.wav':
43
+ # WAV تبدیل به MP3
44
+ output_path = f"{base_name}.mp3"
45
+ AudioSegment.from_wav(input_path).export(output_path, format='mp3')
46
+ return output_path
47
+
48
+ elif ext.lower() in {'.png', '.jpg', '.jpeg'}:
49
+ # تصویر تبدیل به WEBP
50
+ output_path = f"{base_name}.webp"
51
+ Image.open(input_path).save(output_path, 'WEBP')
52
+ return output_path
53
+
54
+ # در صورت نداشتن تغییر، همان مسیر بازگردانده می‌شود.
55
+ return input_path
56
+
57
+ @app.route('/convert', methods=['POST'])
58
+ def handle_conversion():
59
+ if 'file' not in request.files:
60
+ return {"error": "No file uploaded"}, 400
61
+
62
+ file = request.files['file']
63
+ if not file or file.filename == '':
64
+ return {"error": "Empty filename"}, 400
65
+
66
+ if not allowed_file(file.filename):
67
+ return {"error": "Unsupported file type"}, 400
68
+
69
+ try:
70
+ with tempfile.TemporaryDirectory() as temp_dir:
71
+ filename = secure_filename(file.filename)
72
+ upload_path = os.path.join(temp_dir, filename)
73
+ file.save(upload_path)
74
+
75
+ file_ext = filename.split('.')[-1].lower()
76
+
77
+ # اگر فایل تکی باشد، عملیات تبدیل روی همان فایل اعمال شود.
78
+ if file_ext in {'pdf', 'wav', 'mp4', 'jpg', 'png', 'jpeg'}:
79
+ converted_path = convert_single_file(upload_path)
80
+ converted_filename = os.path.basename(converted_path)
81
+ return send_file(
82
+ converted_path,
83
+ as_attachment=True,
84
+ download_name=converted_filename
85
+ )
86
+
87
+ # در صورتی که فایل آرشیو باشد: ابتدا استخراج شود
88
+ if filename.endswith('.zip'):
89
+ with zipfile.ZipFile(upload_path, 'r') as z:
90
+ z.extractall(temp_dir)
91
+ else:
92
+ with rarfile.RarFile(upload_path, 'r') as r:
93
+ r.extractall(temp_dir)
94
+
95
+ # تبدیل تمام فایل‌های موجود در آرشیو
96
+ for root, _, files in os.walk(temp_dir):
97
+ for f in files:
98
+ if f != filename:
99
+ input_file = os.path.join(root, f)
100
+ convert_single_file(input_file)
101
+
102
+ # ایجاد فایل آرشیو خروجی
103
+ output_path = os.path.join(temp_dir, "converted.zip")
104
+ with zipfile.ZipFile(output_path, 'w') as z:
105
+ for root, _, files in os.walk(temp_dir):
106
+ for f in files:
107
+ if f != filename:
108
+ full_path = os.path.join(root, f)
109
+ z.write(full_path, arcname=f)
110
+
111
+ return send_file(
112
+ output_path,
113
+ as_attachment=True,
114
+ download_name="converted_files.zip"
115
+ )
116
+
117
+ except Exception as e:
118
+ return {"error": f"Processing failed: {str(e)}"}, 500
119
+ finally:
120
+ try:
121
+ shutil.rmtree(temp_dir, ignore_errors=True)
122
+ except Exception:
123
+ pass
124
+
125
+ if __name__ == '__main__':
126
+ app.run(host='0.0.0.0', port=7860)
app.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+ import requests
4
+ from threading import Thread
5
+ from flask import Flask, request, send_file
6
+ from werkzeug.utils import secure_filename
7
+ from pdf2image import convert_from_path
8
+ from PIL import Image
9
+ from moviepy.editor import VideoFileClip
10
+ from pydub import AudioSegment
11
+ import streamlit as st
12
+
13
+ # Fix werkzeug compatibility for older versions if needed
14
+ from werkzeug.urls import url_quote
15
+
16
+ # Flask API Setup (برای اینجا فقط به هدف اجرا به عنوان پس‌زمینه استفاده می‌شود)
17
+ app = Flask(__name__)
18
+ ALLOWED_EXTENSIONS = {'zip', 'rar', 'pdf', 'wav', 'mp4', 'jpg', 'png', 'jpeg'}
19
+
20
+ def allowed_file(filename):
21
+ return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
22
+
23
+ # راه‌اندازی API به عنوان پردازش پس‌زمینه
24
+ def run_api():
25
+ # اجرای فایل api.py به صورت subprocess.
26
+ subprocess.run(['python', 'api.py'])
27
+
28
+ # Streamlit UI
29
+ def streamlit_app():
30
+ st.set_page_config(page_title="File Converter", layout="wide")
31
+
32
+ TEXTS = {
33
+ "English": {
34
+ "title": "Universal File Converter",
35
+ "desc": "Convert files/archives (ZIP/RAR/PDF/WAV/MP4/IMG)",
36
+ "upload": "Upload File",
37
+ "error_type": "Unsupported file type!",
38
+ "success": "Conversion Successful!",
39
+ "download": "Download"
40
+ },
41
+ "فارسی": {
42
+ "title": "مبدل جهانی فایل",
43
+ "desc": "تبدیل فایل/آرشیو (ZIP/RAR/PDF/WAV/MP4/تصویر)",
44
+ "upload": "آپلود فایل",
45
+ "error_type": "نوع فایل پشتیبانی نمیشود!",
46
+ "success": "تبدیل با موفقیت انجام شد!",
47
+ "download": "دانلود"
48
+ }
49
+ }
50
+
51
+ lang = st.sidebar.selectbox("", ["English", "فارسی"])
52
+ t = TEXTS[lang]
53
+
54
+ st.title(t["title"])
55
+ st.markdown(f"**{t['desc']}**")
56
+
57
+ uploaded = st.file_uploader(t["upload"], type=ALLOWED_EXTENSIONS)
58
+
59
+ if uploaded:
60
+ file_extension = uploaded.name.split('.')[-1].lower()
61
+ if file_extension not in ALLOWED_EXTENSIONS:
62
+ st.error(t["error_type"])
63
+ elif st.button("Convert"):
64
+ try:
65
+ with st.spinner("Processing..."):
66
+ response = requests.post(
67
+ "http://localhost:7860/convert",
68
+ files={"file": (uploaded.name, uploaded.getvalue(), uploaded.type)},
69
+ timeout=300
70
+ )
71
+
72
+ if response.status_code == 200:
73
+ # استخراج نام فایل خروجی از header Content-Disposition
74
+ cd = response.headers.get('Content-Disposition', '')
75
+ filename = None
76
+ if 'filename=' in cd:
77
+ filename = cd.split("filename=")[1].strip().strip('"')
78
+ else:
79
+ filename = f"converted_{uploaded.name}"
80
+
81
+ st.success(t["success"])
82
+ st.download_button(
83
+ label=t["download"],
84
+ data=response.content,
85
+ file_name=filename,
86
+ )
87
+ else:
88
+ st.error(f"Error {response.status_code}: {response.text}")
89
+
90
+ except Exception as e:
91
+ st.error(f"Connection error: {str(e)}")
92
+
93
+ if __name__ == '__main__':
94
+ # اجرای API داخل یک ترد پس‌زمینه (در صورتی که نیاز به اجرای همزمان داشته باشید)
95
+ Thread(target=run_api, daemon=True).start()
96
+ # اجرای رابط کاربری Streamlit
97
+ streamlit_app()
packages.txt CHANGED
@@ -1,3 +1,2 @@
1
- ffmpeg
2
- libmagic1
3
- poppler-utils
 
1
+ poppler-utils
2
+ ffmpeg
 
requirements.txt CHANGED
@@ -1,11 +1,11 @@
1
- waitress==2.1.2
 
 
2
  streamlit==1.22.0
3
  python-magic==0.4.27
4
  pdf2image==1.16.3
5
- pillow==10.0.1
6
  pydub==0.25.1
7
  moviepy==1.0.3
8
  rarfile==4.0
9
- Flask==2.0.3
10
- Werkzeug==2.0.3
11
  requests
 
1
+ # requirements.txt
2
+ Flask==2.0.3
3
+ Werkzeug==2.0.3 # نسخه سازگار با url_quote
4
  streamlit==1.22.0
5
  python-magic==0.4.27
6
  pdf2image==1.16.3
7
+ Pillow==10.0.1
8
  pydub==0.25.1
9
  moviepy==1.0.3
10
  rarfile==4.0
 
 
11
  requests