added main script + html
This commit is contained in:
parent
d4bbeb043f
commit
f25d49b0e7
49
landing.html
Normal file
49
landing.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{name}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre style="font-size: 1.5em;">
|
||||||
|
{name} File Upload and URL Shortener
|
||||||
|
|
||||||
|
Welcome to the {name} file upload and URL shortening service.
|
||||||
|
This service allows you to easily upload files or shorten URLs for quick access.
|
||||||
|
Files are stored for {expiration_days} days, and URLs are shortened for convenient sharing.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
Upload a file:
|
||||||
|
curl -F file=@yourfile.ext {base_url}/
|
||||||
|
|
||||||
|
Shorten a URL:
|
||||||
|
curl -d "url=https://example.com" {base_url}/shorten
|
||||||
|
|
||||||
|
Details:
|
||||||
|
|
||||||
|
Files uploaded to this service are stored for {expiration_days} days or until they are automatically cleaned up.
|
||||||
|
The maximum file size is {max_file_size}MB.
|
||||||
|
URLs shortened with this service will redirect to the original URL for the same period.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
File upload:
|
||||||
|
curl -F file=@document.pdf {base_url}/
|
||||||
|
Response:
|
||||||
|
{base_url}/abcdef
|
||||||
|
|
||||||
|
URL shortening:
|
||||||
|
curl -d "url=https://example.com" {base_url}/shorten
|
||||||
|
Response:
|
||||||
|
{base_url}/ghijkl
|
||||||
|
|
||||||
|
Disclaimer:
|
||||||
|
|
||||||
|
This service is provided as-is with no guarantees.
|
||||||
|
Uploaded files and shortened URLs are not private and can be accessed by anyone with the link.
|
||||||
|
Use at your own risk.
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
99
main.py
99
main.py
@ -1,67 +1,73 @@
|
|||||||
import os
|
import os, uuid, time, json, sqlite3, threading
|
||||||
import uuid
|
from flask import Flask, request, redirect, send_from_directory, abort, render_template_string
|
||||||
import time
|
|
||||||
import json
|
|
||||||
import threading
|
|
||||||
from flask import Flask, request, redirect, send_from_directory, abort
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
# config
|
with open('config.json') as f:
|
||||||
UPLOAD_FOLDER = './uploads'
|
config = json.load(f)
|
||||||
MAX_FILE_SIZE = 1024 * 1024 * 100 # last number = megabytes
|
|
||||||
EXPIRATION_TIME = 60 * 60 * 24 * 7 # last number = days
|
|
||||||
DATA_FILE = 'data.json'
|
|
||||||
URL_PREFIX = 'http://localhost:5000/'
|
|
||||||
|
|
||||||
if not os.path.exists(UPLOAD_FOLDER):
|
UPLOAD_FOLDER = config['upload_folder']
|
||||||
os.makedirs(UPLOAD_FOLDER)
|
MAX_FILE_SIZE = config['max_file_size']
|
||||||
|
EXPIRATION_TIME = config['expiration_time']
|
||||||
|
DATA_FILE = config['data_file']
|
||||||
|
URL_PREFIX = config['base_url']
|
||||||
|
NAME = config['name']
|
||||||
|
|
||||||
|
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
||||||
|
|
||||||
|
def init_db():
|
||||||
|
with sqlite3.connect(DATA_FILE) as conn:
|
||||||
|
conn.execute('CREATE TABLE IF NOT EXISTS files (key TEXT PRIMARY KEY, type TEXT NOT NULL, path TEXT, url TEXT, expiry REAL)')
|
||||||
|
|
||||||
|
init_db()
|
||||||
|
|
||||||
def load_data():
|
def load_data():
|
||||||
if os.path.exists(DATA_FILE):
|
with sqlite3.connect(DATA_FILE) as conn:
|
||||||
with open(DATA_FILE, 'r') as f:
|
return {row[0]: {'type': row[1], 'path': row[2], 'url': row[3], 'expiry': row[4]} for row in conn.execute('SELECT * FROM files')}
|
||||||
return json.load(f)
|
|
||||||
return {}
|
def save_data():
|
||||||
|
with sqlite3.connect(DATA_FILE) as conn:
|
||||||
|
conn.execute('DELETE FROM files')
|
||||||
|
conn.executemany('INSERT INTO files VALUES (?, ?, ?, ?, ?)',
|
||||||
|
[(k, v['type'], v.get('path'), v.get('url'), v['expiry']) for k, v in data.items()])
|
||||||
|
|
||||||
data = load_data()
|
data = load_data()
|
||||||
|
|
||||||
def save_data():
|
|
||||||
with open(DATA_FILE, 'w') as f:
|
|
||||||
json.dump(data, f)
|
|
||||||
|
|
||||||
def cleanup_files():
|
def cleanup_files():
|
||||||
while True:
|
while True:
|
||||||
time.sleep(60 * 60)
|
time.sleep(3600)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
for key, item in list(data.items()):
|
expired_keys = [k for k, v in data.items() if v['expiry'] < now]
|
||||||
if 'expiry' in item and now > item['expiry']:
|
for k in expired_keys:
|
||||||
try:
|
if data[k]['type'] == 'file':
|
||||||
os.remove(item['path'])
|
os.remove(data[k]['path'])
|
||||||
except Exception as e:
|
data.pop(k)
|
||||||
print(f"Error removing file {item['path']}: {e}")
|
|
||||||
del data[key]
|
|
||||||
save_data()
|
save_data()
|
||||||
|
|
||||||
threading.Thread(target=cleanup_files, daemon=True).start()
|
threading.Thread(target=cleanup_files, daemon=True).start()
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET'])
|
||||||
|
def landing_page():
|
||||||
|
with open('landing.html') as f:
|
||||||
|
html = f.read().format(
|
||||||
|
name=NAME,
|
||||||
|
base_url=URL_PREFIX.rstrip('/'),
|
||||||
|
expiration_days=EXPIRATION_TIME // 86400,
|
||||||
|
max_file_size=MAX_FILE_SIZE // 1048576
|
||||||
|
)
|
||||||
|
return render_template_string(html)
|
||||||
|
|
||||||
@app.route('/', methods=['POST'])
|
@app.route('/', methods=['POST'])
|
||||||
def upload_file():
|
def upload_file():
|
||||||
file = request.files.get('file')
|
file = request.files.get('file')
|
||||||
if not file:
|
if not file or file.content_length > MAX_FILE_SIZE:
|
||||||
return "No file uploaded\n", 400
|
return "No file uploaded or file too large\n", 400
|
||||||
if file.content_length > MAX_FILE_SIZE:
|
|
||||||
return "File too large\n", 400
|
|
||||||
|
|
||||||
filename = file.filename
|
|
||||||
key = uuid.uuid4().hex[:6]
|
key = uuid.uuid4().hex[:6]
|
||||||
filepath = os.path.join(UPLOAD_FOLDER, f"{key}_{filename}")
|
filepath = os.path.join(UPLOAD_FOLDER, f"{key}_{file.filename}")
|
||||||
file.save(filepath)
|
file.save(filepath)
|
||||||
|
|
||||||
data[key] = {
|
data[key] = {'type': 'file', 'path': filepath, 'expiry': time.time() + EXPIRATION_TIME}
|
||||||
'type': 'file',
|
|
||||||
'path': filepath,
|
|
||||||
'expiry': time.time() + EXPIRATION_TIME
|
|
||||||
}
|
|
||||||
save_data()
|
save_data()
|
||||||
return f"{URL_PREFIX}{key}\n"
|
return f"{URL_PREFIX}{key}\n"
|
||||||
|
|
||||||
@ -72,11 +78,7 @@ def shorten_url():
|
|||||||
return "No URL provided\n", 400
|
return "No URL provided\n", 400
|
||||||
|
|
||||||
key = uuid.uuid4().hex[:6]
|
key = uuid.uuid4().hex[:6]
|
||||||
data[key] = {
|
data[key] = {'type': 'url', 'url': url, 'expiry': time.time() + EXPIRATION_TIME}
|
||||||
'type': 'url',
|
|
||||||
'url': url,
|
|
||||||
'expiry': time.time() + EXPIRATION_TIME
|
|
||||||
}
|
|
||||||
save_data()
|
save_data()
|
||||||
return f"{URL_PREFIX}{key}\n"
|
return f"{URL_PREFIX}{key}\n"
|
||||||
|
|
||||||
@ -88,10 +90,9 @@ def get_content(key):
|
|||||||
|
|
||||||
if item['type'] == 'file':
|
if item['type'] == 'file':
|
||||||
return send_from_directory(UPLOAD_FOLDER, os.path.basename(item['path']))
|
return send_from_directory(UPLOAD_FOLDER, os.path.basename(item['path']))
|
||||||
elif item['type'] == 'url':
|
if item['type'] == 'url':
|
||||||
return redirect(item['url'])
|
return redirect(item['url'])
|
||||||
else:
|
abort(404)
|
||||||
abort(404)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host='0.0.0.0', port=5000)
|
app.run(host='0.0.0.0', port=5000)
|
||||||
|
Loading…
Reference in New Issue
Block a user