├── .gitignore ├── README.md ├── application.py ├── requirements.txt ├── static ├── guide-screenshots │ ├── account1.png │ └── cors1.png └── media │ └── default.png └── templates └── account.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.sw* 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FlaskDirectUploader 2 | 3 | 4 | ## Licensing 5 | 6 | The files in this repository are, unless stated otherwise, released under the Apache License. You are free to redistribute this code with or without modification. The full license text is available [here](http://www.apache.org/licenses/LICENSE-2.0). 7 | 8 | 9 | ## Direct-to-S3 uploads in a Python application running on Heroku 10 | 11 | Simple example demonstrating how to accomplish a direct upload to Amazon S3 in a Python web application. 12 | 13 | The example focuses on Flask as the web framework and is targeted for use on the Heroku platform. However, nearly all of the code could be used as-is in other Python frameworks (such as Bottle and Django). An example using Python 3 and Django is available [here](https://gist.github.com/RyanBalfanz/f07d827a4818fda0db81). 14 | 15 | This is the companion repository to the Heroku article, [Direct to S3 File Uploads in Python](https://devcenter.heroku.com/articles/s3-upload-python). 16 | 17 | This code is mostly ready to be run as cloned, but a function `update_account()` will need to be defined to handle the storing of the POSTed information. 18 | 19 | 20 | ## Running the application 21 | * Set environment variables for your AWS access key, secret, and bucket name (see [companion article](https://devcenter.heroku.com/articles/s3-upload-python)) 22 | * Run `python application.py` 23 | * Visit [localhost:5000/account](http://localhost:5000/account) to try it out 24 | 25 | 26 | ## Deploying the application 27 | 28 | See the article [Deploying with Git](https://devcenter.heroku.com/articles/git) for more detailed information on deploying to Heroku. 29 | 30 | * Download and install the [Heroku toolbelt](https://toolbelt.heroku.com/) 31 | * Commit your application to a local Git repository (e.g. `git init`, `git add .`, `git commit -m "version 1 commit"`, etc.) 32 | * Create the application on Heroku by adding a Git remote (`$ heroku create`) 33 | * Push your code to the new Heroku repo (`$ git push heroku master`) 34 | -------------------------------------------------------------------------------- /application.py: -------------------------------------------------------------------------------- 1 | #### 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | # 4 | # http://www.apache.org/licenses/LICENSE-2.0 5 | # 6 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 7 | #### 8 | 9 | 10 | from flask import Flask, render_template, request, redirect, url_for 11 | import os, json, boto3 12 | 13 | app = Flask(__name__) 14 | 15 | 16 | # Listen for GET requests to yourdomain.com/account/ 17 | @app.route("/account/") 18 | def account(): 19 | # Show the account-edit HTML page: 20 | return render_template('account.html') 21 | 22 | 23 | # Listen for POST requests to yourdomain.com/submit_form/ 24 | @app.route("/submit-form/", methods = ["POST"]) 25 | def submit_form(): 26 | # Collect the data posted from the HTML form in account.html: 27 | username = request.form["username"] 28 | full_name = request.form["full-name"] 29 | avatar_url = request.form["avatar-url"] 30 | 31 | # Provide some procedure for storing the new details 32 | update_account(username, full_name, avatar_url) 33 | 34 | # Redirect to the user's profile page, if appropriate 35 | return redirect(url_for('profile')) 36 | 37 | 38 | # Listen for GET requests to yourdomain.com/sign_s3/ 39 | # 40 | # Please see https://gist.github.com/RyanBalfanz/f07d827a4818fda0db81 for an example using 41 | # Python 3 for this view. 42 | @app.route('/sign-s3/') 43 | def sign_s3(): 44 | # Load necessary information into the application 45 | S3_BUCKET = os.environ.get('S3_BUCKET') 46 | 47 | # Load required data from the request 48 | file_name = request.args.get('file-name') 49 | file_type = request.args.get('file-type') 50 | 51 | # Initialise the S3 client 52 | s3 = boto3.client('s3') 53 | 54 | # Generate and return the presigned URL 55 | presigned_post = s3.generate_presigned_post( 56 | Bucket = S3_BUCKET, 57 | Key = file_name, 58 | Fields = {"acl": "public-read", "Content-Type": file_type}, 59 | Conditions = [ 60 | {"acl": "public-read"}, 61 | {"Content-Type": file_type} 62 | ], 63 | ExpiresIn = 3600 64 | ) 65 | 66 | # Return the data to the client 67 | return json.dumps({ 68 | 'data': presigned_post, 69 | 'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name) 70 | }) 71 | 72 | 73 | # Main code 74 | if __name__ == '__main__': 75 | port = int(os.environ.get('PORT', 5000)) 76 | app.run(host='0.0.0.0', port = port) 77 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | boto3==1.3.1 2 | Flask==0.10.1 3 | Jinja2==2.8 4 | Werkzeug==0.11.3 5 | -------------------------------------------------------------------------------- /static/guide-screenshots/account1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willwebberley/FlaskDirectUploader/ce93241e80b9ac10c2e55d65ade4e23a7489d58d/static/guide-screenshots/account1.png -------------------------------------------------------------------------------- /static/guide-screenshots/cors1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willwebberley/FlaskDirectUploader/ce93241e80b9ac10c2e55d65ade4e23a7489d58d/static/guide-screenshots/cors1.png -------------------------------------------------------------------------------- /static/media/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willwebberley/FlaskDirectUploader/ce93241e80b9ac10c2e55d65ade4e23a7489d58d/static/media/default.png -------------------------------------------------------------------------------- /templates/account.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Edit your account

5 | 6 |
7 | 8 |

Your avatar

9 | 10 | 11 |

Please select a file

12 | 13 | 14 |

Your information

15 | 16 |
17 | 18 |
19 |

20 | 21 |
22 |

Save changes

23 | 24 | 25 |
26 | 27 | 28 | 101 | 102 | 103 | --------------------------------------------------------------------------------