-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.py
executable file
·124 lines (103 loc) · 3.02 KB
/
server.py
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
#!/usr/bin/env python3
"""
Main server file. Runs a flask server which can be used to upload and download files.
"""
from argparse import ArgumentParser, Namespace
from pathlib import Path
from socket import AF_INET
from flask import (
Flask,
flash,
redirect,
render_template,
request,
send_from_directory, # pyright: ignore
)
from flask_qrcode import QRcode
from qrcode.main import QRCode
from werkzeug.serving import get_interface_ip
from werkzeug.utils import secure_filename
from werkzeug.wrappers import Response
HOSTNAME = "0.0.0.0"
PORT = 8000
IP = f"http://{get_interface_ip(AF_INET)}:{PORT}"
FOLDER = "files"
app = Flask(__name__)
app.secret_key = "Some"
QRcode(app)
local_path = Path(__file__).parent.joinpath(FOLDER)
def print_qrcode(data: str) -> None:
"""Print a qrcode to the terminal"""
qr = QRCode()
qr.add_data(data)
qr.make(fit=True)
qr.print_ascii(invert=True)
@app.route("/")
def root():
"""
Entry point and home page. Render templates/index.html
"""
return render_template(
"index.html",
ip=IP,
files=map(lambda path: path.name, local_path.iterdir()),
)
@app.route(f"/{FOLDER}/<path:filename>", methods=["GET", "POST"])
def download(filename: str) -> Response:
"""
Navigating to the a file path
for a valid file will download that file.
"""
return send_from_directory(local_path, filename)
@app.route("/delete/<path:filename>", methods=["GET"])
def delete(filename: str) -> Response:
"""
Navigating to /delete/filename will delete filename
"""
try:
local_path.joinpath(filename).unlink()
except FileNotFoundError:
flash("File not found, no file deleted")
return redirect("/")
@app.route("/upload", methods=["POST"])
def upload() -> Response:
"""
Accept a POST request with a file object.
If it is valid, upload it to the server.
"""
files = request.files.getlist("file")
if not files:
flash("No file provided")
return redirect("/")
for file in files:
path = local_path.joinpath(secure_filename(str(file.filename)))
if path.exists():
flash("Filename already exists on server")
return redirect("/")
file.save(path) # pyright: ignore
return redirect("/")
def get_args() -> Namespace:
"""Get command line arguments to local file server"""
parser = ArgumentParser(
description="Flask server to upload and download files on a local area network",
)
parser.add_argument(
"download_folder",
nargs="?",
default=FOLDER,
help=f"Folder to store and display downloads. Default is `{FOLDER}`",
)
return parser.parse_args()
def main() -> None:
"""Entry point for local file server"""
global local_path # pylint: disable=global-statement
args = get_args()
local_path = Path(args.download_folder)
print_qrcode(IP)
app.run(
host=HOSTNAME,
port=PORT,
debug=False,
)
if __name__ == "__main__":
main()