Commits

Stefano Costa  committed 4122031

[app] Add file uploads for data, make app more robust

  • Participants
  • Parent commits ad087e1

Comments (0)

Files changed (2)

File requirements.txt

 Flask
+Flask-Uploads
 -e hg+https://bitbucket.org/steko/totalopenstation/#egg=totalopenstation
 from flask import Flask, request, session, g, redirect, url_for, \
      abort, render_template, flash
 
+from flaskext.uploads import (UploadSet, configure_uploads, ALL,
+                              UploadNotAllowed, patch_request_class)
+
 from totalopenstation.formats import BUILTIN_INPUT_FORMATS
 from totalopenstation.output import BUILTIN_OUTPUT_FORMATS
 
 
 # create our little application :)
 app = Flask(__name__)
+
+
+UPLOADS_DEFAULT_DEST = '/tmp/topscloud'
+
 app.config.from_object(__name__)
 
 app.config.from_envvar('FLASKR_SETTINGS', silent=True)
 
-SECRET_KEY = 'oh well secret'
+SECRET_KEY = '097gtqwfxughqd98h1xx08y12x98ljaHPUIOG'
 app.secret_key = SECRET_KEY
 
-@app.route('/')
+uploaded_data = UploadSet('data', ALL)
+configure_uploads(app, uploaded_data)
+
+patch_request_class(app, 512 * 1024)
+
+@app.route('/convert', methods=['GET'])
 def home():
     input_formats = [ {'k': k, 'v':v[2]} for k, v in sorted(BUILTIN_INPUT_FORMATS.items()) ]
     output_formats = [ {'k': k, 'v':v[2]} for k, v in sorted(BUILTIN_OUTPUT_FORMATS.items()) ]
+    input_formats.insert(0, {'',''})
+    output_formats.insert(0, {'',''})
     return render_template('home.html', input_formats=input_formats, output_formats = output_formats)
 
-@app.route('/export', methods=['POST'])
-def export():
-    inputclass = BUILTIN_INPUT_FORMATS[request.form['input_format']]
-    if isinstance(inputclass, tuple):
-        mod, cls, ifname = inputclass
-        inputclass = getattr(
-            __import__('totalopenstation.formats.' + mod, None, None, [cls]), cls)
-
-    outputclass = BUILTIN_OUTPUT_FORMATS[request.form['output_format']]
-    if isinstance(outputclass, tuple):
-        mod, cls, ofname = outputclass
-        outputclass = getattr(
-            __import__('totalopenstation.output.' + mod, None, None, [cls]), cls)
-
-    parsed_data = inputclass(request.form['data'])
-    parsed_points = parsed_data.points
-    output = outputclass(parsed_points).process()
-
-    data = {'title': request.form['title'],
-            'exported': output,
-            'if': ifname,
-            'of': ofname}
-    flash('Uploaded data was successfully exported')
-    return render_template('export.html', data=data)
+@app.route('/')
+def about():
+    return render_template('about.html')
+
+@app.route('/convert', methods=['POST'])
+def convert():
+    if request.method == 'GET':
+        return redirect(url_for('home'))
+    data = request.files['data']
+    title = request.form['title']
+    if not (data and title):
+        flash("You must fill in all the fields", 'error')
+        return redirect(url_for('home'))
+    if request.form['input_format'] == '' or request.form['output_format'] == '':
+        flash("Please choose both an input and output format", 'error')
+        return redirect(url_for('home'))
+    else:
+
+        inputclass = BUILTIN_INPUT_FORMATS[request.form['input_format']]
+        if isinstance(inputclass, tuple):
+            mod, cls, ifname = inputclass
+            inputclass = getattr(
+                __import__('totalopenstation.formats.' + mod, None, None, [cls]), cls)
+
+        outputclass = BUILTIN_OUTPUT_FORMATS[request.form['output_format']]
+        if isinstance(outputclass, tuple):
+            mod, cls, ofname = outputclass
+            outputclass = getattr(
+                __import__('totalopenstation.output.' + mod, None, None, [cls]), cls)
+
+        try:
+            filename = uploaded_data.save(data)
+            filepath = uploaded_data.path(filename)
+        except UploadNotAllowed:
+            flash("The upload was not allowed", 'error')
+            return redirect(url_for('home'))
+        else:
+            datafile = open(filepath).read()
+            parsed_data = inputclass(datafile)
+            parsed_points = parsed_data.points
+            numpoints = len(parsed_points)
+            if numpoints == 0:
+                flash('There was a problem processing your data. Did you choose the correct format?', 'error')
+                return redirect(url_for('home'))
+            output = outputclass(parsed_points).process()
+
+            data = {'title': title,
+                    'exported': output,
+                    'if': ifname,
+                     'of': ofname,
+                     'numpoints': numpoints}
+            flash('Uploaded data was successfully exported', 'success')
+            return render_template('export.html', data=data)
+
+@app.errorhandler(413)
+def too_large(error):
+    flash('The file you tried to upload is larger than 500 KB', 'error')
+    return render_template('home.html'), 413
 
 if __name__ == '__main__':
     app.run()