Skip to content

Instantly share code, notes, and snippets.

@stephen-w-pracy
Last active April 16, 2025 23:17
Show Gist options
  • Save stephen-w-pracy/f766ac1fd124cc38f9e5b256ed6c5831 to your computer and use it in GitHub Desktop.
Save stephen-w-pracy/f766ac1fd124cc38f9e5b256ed6c5831 to your computer and use it in GitHub Desktop.
A single python script for fast and dirty file transfer.

Fast and Dirty File Transfer

This is a simple app for low-hassle file transfer over HTTP. It serves a webpage to upload and download files. It has rudimentary security in the form of a runtime secret code.

Screenshot of app experience

Requirements

Python 3

Installation

Put app.py somewhere on your host. Then in the same directory, create a files subdirectory:

mkdir files

Usage

python3 app.py

This will emit a new access code. When you visit the host at port 8000, you will be prompted for that code. When entered correctly, it's saved in a cookie and checked on each subsequent request.

All uploaded files will be written to files/. All files in files/ will be displayed and downloadable.

#!/usr/bin/env python3
import os
import http.server
import socketserver
import random
import string
from urllib.parse import unquote
from cgi import FieldStorage
PORT = 8000
FILES_DIR = "files"
ACCESS_CODE = ''.join(random.choices(string.digits, k=6))
os.makedirs(FILES_DIR, exist_ok=True)
HTML_PAGE = """
<!DOCTYPE html>
<html>
<head><title>File Share</title></head>
<body>
<script>
const CODE = "{}";
const cookie = document.cookie.split('; ').find(r => r.startsWith('access_code='));
let accessOK = cookie && cookie.split('=')[1] === CODE;
if (!accessOK) {{
const input = prompt("Enter access code:");
if (input !== CODE) {{
document.body.innerHTML = "<h1>Access denied</h1>";
throw new Error("Forbidden");
}} else {{
document.cookie = "access_code=" + input + "; path=/";
location.reload();
}}
}} else {{
document.write(`
<h2>Upload File</h2>
<form enctype="multipart/form-data" method="post">
<input name="file" type="file"/>
<input type="submit" value="Upload"/>
</form>
<h2>Files</h2>
<ul>
{}
</ul>
`);
}}
</script>
</body>
</html>
"""
class Handler(http.server.SimpleHTTPRequestHandler):
def has_valid_code(self):
cookie_header = self.headers.get('Cookie', '')
for cookie in cookie_header.split(';'):
if cookie.strip().startswith('access_code='):
value = cookie.strip().split('=')[1]
return value == ACCESS_CODE
return False
def list_files(self):
files = os.listdir(FILES_DIR)
return [f"<li><a href='/files/{f}'>{f}</a></li>" for f in files if os.path.isfile(os.path.join(FILES_DIR, f))]
def do_GET(self):
if self.path == '/':
# Always serve this, even without cookie
file_links = "\n".join(self.list_files())
content = HTML_PAGE.format(ACCESS_CODE, file_links).encode()
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(len(content)))
self.end_headers()
self.wfile.write(content)
elif self.path.startswith('/files/'):
if not self.has_valid_code():
self.send_error(403, "Access code required")
return
file_path = os.path.join(FILES_DIR, os.path.basename(unquote(self.path[len('/files/'):])))
if os.path.exists(file_path):
self.path = '/' + file_path
return http.server.SimpleHTTPRequestHandler.do_GET(self)
else:
self.send_error(404, "File not found")
else:
self.send_error(403)
def do_POST(self):
if not self.has_valid_code():
self.send_error(403, "Access code required")
return
form = FieldStorage(fp=self.rfile, headers=self.headers, environ={
'REQUEST_METHOD': 'POST',
'CONTENT_TYPE': self.headers['Content-Type'],
})
file_field = form['file']
if file_field.filename:
dest_path = os.path.join(FILES_DIR, os.path.basename(file_field.filename))
with open(dest_path, 'wb') as f:
f.write(file_field.file.read())
self.send_response(303)
self.send_header('Location', '/')
self.end_headers()
if __name__ == "__main__":
print(f"Access code: {ACCESS_CODE}")
print(f"Serving at http://0.0.0.0:{PORT}")
with socketserver.TCPServer(("", PORT), Handler) as httpd:
httpd.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment