-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
170 lines (135 loc) · 6.18 KB
/
app.py
File metadata and controls
170 lines (135 loc) · 6.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import streamlit as st
import cloudinary
import cloudinary.uploader
import cloudinary.api
import qrcode
from io import BytesIO
import time
import urllib.parse
# --- PAGE CONFIG ---
st.set_page_config(page_title="SecuredFileShare | Safe File Hosting", layout="centered")
st.title("🔐 Secured File Share")
st.caption("Upload any file securely with password and expiry control.")
st.markdown("📁 Files auto-delete after the selected time. Each file has a secure access link & QR code.")
# --- HOW TO USE ---
with st.expander("ℹ️ How to Use SecureShare", expanded=True):
st.markdown("""
**Step 1:** Set a password below to secure your file
**Step 2:** Choose how many hours the file should remain accessible
**Step 3:** Upload any file you want to share
**Step 4:** You'll get a secure access link & QR code to share
**Step 5:** Anyone with the link must enter the password to access the file
⚠️ The file will automatically be deleted after the set time.
""")
# --- INIT CONFIG ---
cloudinary.config(
cloud_name=st.secrets["cloudinary"]["cloud_name"],
api_key=st.secrets["cloudinary"]["api_key"],
api_secret=st.secrets["cloudinary"]["api_secret"]
)
UPLOAD_FOLDER = st.secrets["cloudinary"]["UPLOAD_FOLDER"]
# --- FILE ACCESS (via link) ---
query_params = st.query_params
file_id = query_params.get("file")
if file_id:
st.markdown("### 🔗 File Access")
st.info(f"Accessing file ID: `{file_id}`")
password_input = st.text_input("Enter password to access file", type="password")
try:
file_details = cloudinary.api.resource(file_id, resource_type="raw")
metadata = file_details.get("context", {}).get("custom", {})
if not metadata:
st.error("❌ No metadata found. File may be expired or not uploaded via SecureShare.")
st.stop()
original_password = metadata.get("password")
expires_raw = metadata.get("expires_at")
expires_at = int(float(expires_raw)) if expires_raw else 0
current_time = int(time.time())
if expires_at and current_time > expires_at:
st.error("⏰ This file has expired and is no longer accessible.")
st.stop()
if str(password_input).strip() == str(original_password).strip():
time_left = expires_at - current_time
mins_left = max(1, int(time_left / 60))
st.success(f"✅ Access granted! Time remaining: {mins_left} minutes")
file_url = file_details["secure_url"]
file_name = file_details.get("original_filename", "download")
st.markdown("🔗 **Secure Download Link:**")
st.code(file_url)
st.markdown(f"[⬇️ Click to Download File]({file_url})", unsafe_allow_html=True)
qr = qrcode.make(file_url)
buf = BytesIO()
qr.save(buf, format="PNG")
buf.seek(0)
st.image(buf, caption="📱 Scan to download", width=180)
st.markdown(f"**🆔 File ID:** `{file_id}`")
elif password_input:
st.error("❌ Incorrect password.")
st.stop()
except cloudinary.exceptions.NotFound:
st.error("⚠️ File not found. It might have been deleted or the ID is invalid.")
st.stop()
# --- UPLOAD SECTION ---
st.markdown("### 📤 Upload New Files")
file_password = st.text_input("🔑 Set a password to access the file(s)", type="password")
if file_password.strip():
expiry_hours = st.slider("⏰ Set expiry time (hours)", 1, 48, 6)
uploaded_files = st.file_uploader("📂 Select file(s) to upload", type=None, accept_multiple_files=True)
if uploaded_files:
for uploaded_file in uploaded_files:
st.markdown("---")
st.info(f"Uploading `{uploaded_file.name}`...")
expires_at = int(time.time() + expiry_hours * 3600)
try:
context_str = f"password={file_password}|expires_at={str(expires_at)}"
result = cloudinary.uploader.upload(
uploaded_file,
folder=UPLOAD_FOLDER,
resource_type="raw",
use_filename=True,
unique_filename=True,
context=context_str
)
file_url = result.get("secure_url")
public_id = result.get("public_id")
base_url = "https://secured-file-share.streamlit.app/"
access_url = f"{base_url}?file={urllib.parse.quote(public_id)}"
st.success("✅ Upload successful!")
st.markdown("🔗 **Secure Access Link (share this):**")
st.code(access_url)
qr = qrcode.make(access_url)
buf = BytesIO()
qr.save(buf, format="PNG")
buf.seek(0)
st.image(buf, caption="📱 Scan to access file", width=180)
time_left_min = int((expires_at - time.time()) / 60)
st.markdown(f"""
**🆔 Public ID:** `{public_id}`
**⏱️ Time left:** {time_left_min} minutes
**📂 Folder:** `{UPLOAD_FOLDER}`
""")
except Exception as e:
st.error(f"❌ Upload failed: {str(e)}")
else:
st.info("📂 Please select at least one file to upload.")
else:
st.warning("🔐 Please set a password to enable file upload.")
# --- FOOTER ---
st.markdown("---")
st.markdown("### ℹ️ About SecureShare")
st.write("""
**SecureShare** is a privacy-first file sharing tool built with **Streamlit** and **Cloudinary**.
Features include:
✅ Upload any file format (PDF, EXE, ZIP, DOCX, etc.)
✅ Set custom expiry time
✅ Password-protect every upload
✅ QR code & shareable secure link
✅ Files auto-delete after expiry
✅ No login required
""")
st.markdown("""
---
🛠️ **Open Source:**
View or contribute on GitHub 👉 [github.com/vaibhavrawat27/secured-file-share](https://github.com/VaibhavRawat27/secured-file-share)
""")
st.markdown("📧 Built by Vaibhav Rawat • ☁️ Powered by Cloudinary • 🐍 Made with Python & Streamlit")