2021-10-01
It's sometimes handy to have a script that allows a visitor (from the same network) to visit the page and upload a file. This is sort of like the inverse of python -m http.server
. The UI is bare-bones and can be vastly improved (drag and drop is an obvious feature to add), but I've found this useful on a few occasions to transfer files on a LAN with no fuss.
This relies on the python-multipart package...it was an expedient choice when I threw this together, and while the Github repo for python-multipart is updated regularly, the PyPI package for python-multipart is not, so I'd probably port this to use multipart instead if I were to revisit it.
#!/usr/bin/env python3
import multipart
from wsgiref.simple_server import make_server
PAGE="""
<html>
<head>
<title>Drop</title>
</head>
<body>
<h1>Drop</h1>
<div>
<form method="post" enctype="multipart/form-data">
<input type="file" id="file" name="filename">
<input value="Upload" type="submit">
</form>
</div>
</body>
</html>
"""
def drop(environ, start_response):
fields = {}
files = {}
def on_field(field):
fields[field.field_name.decode()] = field.value
def on_file(file):
files[file.field_name.decode()] = {'name': file.file_name.decode(), 'file_object': file.file_object}
content = PAGE
if environ['REQUEST_METHOD'] == 'POST':
multipart_headers = {'Content-Type': environ['CONTENT_TYPE']}
multipart_headers['Content-Length'] = environ['CONTENT_LENGTH']
multipart.parse_form(multipart_headers, environ['wsgi.input'], on_field, on_file)
file_data = files["filename"]
print(file_data)
file_object = file_data["file_object"]
file_object.seek(0)
data = file_object.read()
print("The file is {} bytes".format(len(data)))
with open(file_data["name"], "wb") as f:
f.write(data)
content = [content.encode('utf-8')]
status = '200 OK'
headers = [('Content-type', 'text/html; charset=utf-8')]
start_response(status, headers)
return content
def run():
port = 10000
with make_server('', port, drop) as httpd:
print("Serving on port {}...".format(port))
httpd.serve_forever()
if __name__ == "__main__":
run()