Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
FileTransfer3.py
# File Transfer for Pythonista
# ============================
# This script allows you to transfer Python files from
# and to Pythonista via local Wifi.
# It starts a basic HTTP server that you can access
# as a web page from your browser.
# When you upload a file that already exists, it is
# renamed automatically.
# From Pythonista's settings, you can add this script
# to the actions menu of the editor for quick access.
#
# Get Pythonista for iOS here:
# http://omz-software.com/pythonista
#
# --- converted to pythonista 3 with 2to3 and a few hacks
from http.server import BaseHTTPRequestHandler
import urllib.parse
import urllib.request, urllib.parse, urllib.error
import cgi
import editor
import console
from socket import gethostname
import os
from io import StringIO
TEMPLATE = ('<!DOCTYPE html><html><head>' +
'<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/'+
'css/bootstrap-combined.min.css" rel="stylesheet"></head><body>' +
'<div class="navbar"><div class="navbar-inner">' +
'<a class="brand" href="#">Pythonista File Transfer</a>' +
'</div></div><div class="container">' +
'<h2>Upload File</h2>{{ALERT}}'
'<p><form action="/" method="POST" enctype="multipart/form-data">' +
'<div class="form-actions">' +
'<input type="file" name="file"></input><br/><br/>' +
'<button type="submit" class="btn btn-primary">Upload</button>' +
'</div></form></p><hr/><h2>Download Files</h2>' +
'{{FILES}}</div></body></html>')
class TransferRequestHandler(BaseHTTPRequestHandler):
def get_unused_filename(self, filename):
if not os.path.exists(filename):
return filename
basename, ext = os.path.splitext(filename)
suffix_n = 1
while True:
alt_name = basename + '-' + str(suffix_n) + ext
if not os.path.exists(alt_name):
return alt_name
suffix_n += 1
def get_html_file_list(self):
buffer = StringIO()
buffer.write('<ul>')
root_dir = os.path.expanduser('~/Documents')
files = []
for dn, dc, filenames in os.walk(root_dir):
for fn in filenames:
rel_dir = os.path.relpath(dn, root_dir)
if rel_dir != '.':
rel_file = os.path.join(rel_dir, fn)
else:
rel_file = fn
files.append(rel_file)
for filename in files:
if os.path.splitext(filename)[1] == '.py':
buffer.write('<li><a href="%s">%s</a></li>' % (filename, filename))
buffer.write('</ul>')
return buffer.getvalue()
def do_GET(self):
parsed_path = urllib.parse.urlparse(self.path)
path = parsed_path.path
if path == '/':
html = TEMPLATE
html = html.replace('{{ALERT}}', '')
html = html.replace('{{FILES}}', self.get_html_file_list())
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.end_headers()
# fix - encode str to bytes
self.wfile.write(html.encode())
return
file_path = urllib.parse.unquote(path)[1:]
if os.path.isfile(file_path):
self.send_response(200)
self.send_header('Content-Type', 'application/x-python')
self.send_header('Content-Disposition',
'attachment; filename=%s' % file_path)
self.end_headers()
with open(file_path, 'r') as f:
data = f.read()
# fix - turn str into bytes
self.wfile.write(data.encode())
else:
html = TEMPLATE
html = html.replace('{{ALERT}}',
'<div class="alert alert-error">File not found</div>')
html = html.replace('{{FILES}}', self.get_html_file_list())
self.send_response(404)
self.send_header('Content-Type', 'text/html')
self.end_headers()
# fix - turn str into bytes
self.wfile.write(html.encode())
def do_POST(self):
form = cgi.FieldStorage(fp=self.rfile, headers=self.headers,
environ={'REQUEST_METHOD':'POST',
'CONTENT_TYPE':self.headers['Content-Type']})
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.end_headers()
field_item = form['file']
uploaded_filename = None
dest_filename = None
file_data = field_item.file.read()
file_len = len(file_data)
uploaded_filename = field_item.filename
dest_filename = self.get_unused_filename(uploaded_filename)
with open(dest_filename, 'w') as f:
# fix - turn bytes into str
f.write(file_data.decode())
editor.reload_files()
del file_data
html = TEMPLATE
if uploaded_filename != dest_filename:
message = '%s uploaded (renamed to %s).' % (uploaded_filename,
dest_filename)
else:
message = '%s uploaded.' % (uploaded_filename)
html = html.replace('{{ALERT}}',
'<div class="alert alert-success">%s</div>' % (message))
html = html.replace('{{FILES}}', self.get_html_file_list())
self.wfile.write(html.encode())
if __name__ == '__main__':
console.clear()
from http.server import HTTPServer
server = HTTPServer(('', 8080), TransferRequestHandler)
URL = 'http://%s.local:8080' % gethostname()
print('Open this page in your browser:')
console.set_font('Helvetica-Bold', 30)
print(URL)
console.set_font()
print('Tap the stop button when you\'re done.')
server.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment