launch-calcium commited on
Commit
078a3d7
ยท
verified ยท
1 Parent(s): 597a6c5

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +227 -0
app.py ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sqlite3
3
+ import shutil
4
+ import mimetypes
5
+ from datetime import datetime, timezone
6
+ import gradio as gr
7
+
8
+ DB_NAME = "files.db"
9
+ UPLOAD_DIR = "uploads"
10
+ MAX_EMBEDDED_SIZE = 1 * 1024 * 1024 # 1 MB in bytes
11
+
12
+ def init_db(db_path=DB_NAME):
13
+ """Initialize the SQLite database schema if it doesn't exist."""
14
+ conn = sqlite3.connect(db_path)
15
+ cursor = conn.cursor()
16
+ cursor.execute("""
17
+ CREATE TABLE IF NOT EXISTS files (
18
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
19
+ filename TEXT NOT NULL,
20
+ file_type TEXT,
21
+ file_size_bytes INTEGER NOT NULL,
22
+ upload_timestamp TEXT NOT NULL,
23
+ is_large_file INTEGER NOT NULL,
24
+ file_content_blob BLOB,
25
+ relative_path TEXT
26
+ )
27
+ """)
28
+ conn.commit()
29
+ conn.close()
30
+ os.makedirs(UPLOAD_DIR, exist_ok=True)
31
+
32
+ def process_uploaded_files(files, db_path=DB_NAME, upload_dir=UPLOAD_DIR):
33
+ """Process multiple uploaded files and log them into the SQLite database."""
34
+ if not files:
35
+ return "No files uploaded.", get_records_df(db_path), gr.update()
36
+
37
+ init_db(db_path)
38
+ conn = sqlite3.connect(db_path)
39
+ cursor = conn.cursor()
40
+
41
+ uploaded_count = 0
42
+ for file_obj in files:
43
+ # file_obj is a Gradio file object or filepath string depending on Gradio version
44
+ file_path = file_obj.name if hasattr(file_obj, "name") else str(file_obj)
45
+ orig_filename = os.path.basename(file_path)
46
+ file_size = os.path.getsize(file_path)
47
+ file_type, _ = mimetypes.guess_type(file_path)
48
+ if not file_type:
49
+ file_type = "application/octet-stream"
50
+
51
+ timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
52
+
53
+ if file_size > MAX_EMBEDDED_SIZE:
54
+ # File > 1MB: save to uploads directory and reference relative path
55
+ os.makedirs(upload_dir, exist_ok=True)
56
+ dest_filename = f"{int(datetime.now(timezone.utc).timestamp())}_{orig_filename}"
57
+ dest_path = os.path.join(upload_dir, dest_filename)
58
+ shutil.copy(file_path, dest_path)
59
+
60
+ cursor.execute("""
61
+ INSERT INTO files (filename, file_type, file_size_bytes, upload_timestamp, is_large_file, file_content_blob, relative_path)
62
+ VALUES (?, ?, ?, ?, ?, ?, ?)
63
+ """, (orig_filename, file_type, file_size, timestamp, 1, None, dest_path))
64
+ else:
65
+ # File <= 1MB: store binary content directly in database
66
+ with open(file_path, "rb") as f:
67
+ blob_data = f.read()
68
+
69
+ cursor.execute("""
70
+ INSERT INTO files (filename, file_type, file_size_bytes, upload_timestamp, is_large_file, file_content_blob, relative_path)
71
+ VALUES (?, ?, ?, ?, ?, ?, ?)
72
+ """, (orig_filename, file_type, file_size, timestamp, 0, blob_data, None))
73
+
74
+ uploaded_count += 1
75
+
76
+ conn.commit()
77
+ conn.close()
78
+
79
+ df = get_records_df(db_path)
80
+ large_files_dropdown = get_large_files_choices(db_path)
81
+ return f"Successfully processed and logged {uploaded_count} file(s).", df, large_files_dropdown
82
+
83
+ def get_records_df(db_path=DB_NAME):
84
+ """Retrieve database records as a list of lists for Gradio Dataframe."""
85
+ if not os.path.exists(db_path):
86
+ return []
87
+
88
+ conn = sqlite3.connect(db_path)
89
+ cursor = conn.cursor()
90
+ cursor.execute("""
91
+ SELECT id, filename, file_type, file_size_bytes, upload_timestamp, is_large_file,
92
+ CASE WHEN file_content_blob IS NOT NULL THEN 'Stored in DB (BLOB)' ELSE 'Not Stored (BLOB IS NULL)' END as blob_status,
93
+ COALESCE(relative_path, 'N/A') as relative_path
94
+ FROM files
95
+ ORDER BY id DESC
96
+ """)
97
+ rows = cursor.fetchall()
98
+ conn.close()
99
+ return rows
100
+
101
+ def get_large_files_choices(db_path=DB_NAME):
102
+ """Get list of choices for large file download dropdown."""
103
+ if not os.path.exists(db_path):
104
+ return gr.update(choices=[], value=None)
105
+
106
+ conn = sqlite3.connect(db_path)
107
+ cursor = conn.cursor()
108
+ cursor.execute("""
109
+ SELECT id, filename, relative_path
110
+ FROM files
111
+ WHERE is_large_file = 1 AND relative_path IS NOT NULL
112
+ ORDER BY id DESC
113
+ """)
114
+ rows = cursor.fetchall()
115
+ conn.close()
116
+
117
+ choices = [f"ID {r[0]}: {r[1]} ({r[2]})" for r in rows]
118
+ val = choices[0] if choices else None
119
+ return gr.update(choices=choices, value=val)
120
+
121
+ def download_selected_large_file(selected_item, db_path=DB_NAME):
122
+ """Return the file path for the selected large file to allow download."""
123
+ if not selected_item:
124
+ return None
125
+
126
+ try:
127
+ file_id = int(selected_item.split(":")[0].replace("ID", "").strip())
128
+ except Exception:
129
+ return None
130
+
131
+ conn = sqlite3.connect(db_path)
132
+ cursor = conn.cursor()
133
+ cursor.execute("SELECT relative_path FROM files WHERE id = ?", (file_id,))
134
+ row = cursor.fetchone()
135
+ conn.close()
136
+
137
+ if row and row[0] and os.path.exists(row[0]):
138
+ return row[0]
139
+ return None
140
+
141
+ def download_database(db_path=DB_NAME):
142
+ """Return database file for downloading."""
143
+ if os.path.exists(db_path):
144
+ return db_path
145
+ return None
146
+
147
+ # Initialize DB on load
148
+ init_db()
149
+
150
+ # Build Gradio UI
151
+ with gr.Blocks(title="Personal SQL DB Generator") as demo:
152
+ gr.Markdown("# ๐Ÿ—„๏ธ Personal SQL DB File Generator & Logger")
153
+ gr.Markdown(
154
+ "Upload multiple files of any type. Files **<= 1MB** are stored directly as binary BLOBs inside the SQLite database. "
155
+ "Files **> 1MB** are stored on disk with relative path references stored in the database. "
156
+ "You can inspect logged entries, download the complete SQLite `.db` database file, and download big files."
157
+ )
158
+
159
+ with gr.Tab("Upload Files & Log to SQL"):
160
+ file_input = gr.File(
161
+ label="Select or Drag & Drop Multiple Files",
162
+ file_count="multiple",
163
+ type="filepath"
164
+ )
165
+ upload_button = gr.Button("Upload & Log to Database", variant="primary")
166
+ status_output = gr.Textbox(label="Status Log", interactive=False)
167
+
168
+ with gr.Tab("Database Records"):
169
+ refresh_button = gr.Button("๐Ÿ”„ Refresh Database Table")
170
+ db_table = gr.Dataframe(
171
+ headers=["ID", "Filename", "Type", "Size (bytes)", "Timestamp", "Is Large (>1MB)", "BLOB Status", "Relative Path"],
172
+ value=get_records_df(),
173
+ interactive=False,
174
+ wrap=True
175
+ )
176
+
177
+ with gr.Tab("Downloads"):
178
+ with gr.Row():
179
+ with gr.Column():
180
+ gr.Markdown("### ๐Ÿ“ฆ Download SQLite Database")
181
+ db_download_btn = gr.Button("Prepare Database File")
182
+ db_file_output = gr.File(label="Download SQLite DB (.db)")
183
+
184
+ with gr.Column():
185
+ gr.Markdown("### ๐Ÿ“‚ Download Large Files (>1MB)")
186
+ large_files_dropdown = gr.Dropdown(
187
+ label="Select Large File to Download",
188
+ choices=[c for c in get_large_files_choices()["choices"]] if isinstance(get_large_files_choices(), dict) else [],
189
+ interactive=True
190
+ )
191
+ refresh_dropdown_btn = gr.Button("Refresh Large Files List")
192
+ download_large_btn = gr.Button("Prepare Large File Download")
193
+ large_file_output = gr.File(label="Download File")
194
+
195
+ # Event handlers
196
+ upload_button.click(
197
+ fn=process_uploaded_files,
198
+ inputs=[file_input],
199
+ outputs=[status_output, db_table, large_files_dropdown]
200
+ )
201
+
202
+ refresh_button.click(
203
+ fn=get_records_df,
204
+ inputs=[],
205
+ outputs=[db_table]
206
+ )
207
+
208
+ db_download_btn.click(
209
+ fn=download_database,
210
+ inputs=[],
211
+ outputs=[db_file_output]
212
+ )
213
+
214
+ refresh_dropdown_btn.click(
215
+ fn=get_large_files_choices,
216
+ inputs=[],
217
+ outputs=[large_files_dropdown]
218
+ )
219
+
220
+ download_large_btn.click(
221
+ fn=download_selected_large_file,
222
+ inputs=[large_files_dropdown],
223
+ outputs=[large_file_output]
224
+ )
225
+
226
+ if __name__ == "__main__":
227
+ demo.launch()