I'm following the Flask tutorial for image uploading. I also decided to tinker with it a bit so that I can add other features. The website loads locally, but when I actually click on the upload button (after selecting a .png image), I get the following error:
Bad Request. The browser (or proxy) sent a request that this server could not understand.
I've read something about adding an else statement here:
Form sending error, Flask
But I'm not sure how to accommodate it for my needs.
Here is my code:
from flask import Flask, request, session, g, redirect, url_for, \
abort, render_template, flash
from werkzeug import secure_filename
import os
DEBUG = True
SECRET_KEY = 'development key'
USERNAME = 'admin'
PASSWORD = 'default'
#Add parameters for image uploads:
UPLOAD_FOLDER = '/upload_folder/'
ALLOWED_EXTENSIONS = set(['png','jpg','jpeg'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
##app.route('/')
##app.route('/<name>')
#Image uploads:
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.',1)[1] in ALLOWED_EXTENSIONS
#app.route('/',methods=['GET','POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'],filename))
return redirect(url_for('uploaded_file',filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>UPload new File</h1>
<form action="" method=post enctype=multpart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
'''
#Handle errors:
#app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'),404
#render template:
def flaskr(name=None):
return render_template('hello.html',name=name)
#Handle errors:
#app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'),404
if __name__ == '__main__':
app.run()
There is a typo in your html code:
<form action="" method=post enctype=multpart/form-data>
should be multipart and not multpart.
Related
in html, I have
<form method="POST" enctype="multipart/form-data" action="/">
<input type="number" name="speed " id="speed">
<input type="file" id="stl_file">
<input type="submit" value="submit">
</form>
I would like to save the value for speed in json file and save the uploaded stl file as well.
What I did in my app.py is
from flask import Flask, render_template, request,flash, redirect, url_for
from werkzeug.utils import secure_filename
import os
import json
app = Flask(__name__)
ALLOWED_EXTENSIONS = {'stl','STL'}
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route("/")
def index():
return render_template('main.html')
#app.route('/' , methods=['POST'])
def get_data():
if request.method == 'POST':
results =request.form
file = request.files['stl_file']
with open('file.json','w') as f:
json.dump(results, f)
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(filename)
return redirect(url_for('index'))
return render_template('main.html')
if __name__ == '__main__':
app.run()
I can run it and I see my main page. However, when I input a number into speed, upload a file, and click submit, I get
Bad Request
The browser (or proxy) sent a request that this server could not understand.
Any suggestion on that? Thanks in advance.
You haven't defined the name attribute of file.
<input type="file" name="stl_file" id="stl_file">
I want to create a REST API using Flask. I have two files at any given time, I will call my API and send these two files, a python script will run on the API side and send me back a JSON Response. Now this is the overall idea of my application , but I don't know how to do all this. As I do not want to save those two files, just take them as an Input and send the result back, I don't think i will need to save the files. But I do not know how to send files to the API, logic part is ready, I just need to know how to send two files, process them and send back the response in just one API call. Thanks in advance
I have just setup the basic API till now.
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return 'Server works'
if __name__== '__main__':
app.run(debug=True)
Found this on the Flask documentation:
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
'''
In your API backend, you will receive the file by using file = request.files['file']. The name "file" comes from the name of the input tag in the HTML Form you are using to send the file to your backend.
'''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
'''
In this example, the backend is saving the uploaded files to UPLOAD_FOLDER. This example is also using some exception handling to make sure that the user is uploading the correct type of file types.
[EDIT] I misread your question. If you just want to send back a JSON response instead of JSON containing the files content you would do this:
return jsonify({"response": "success"})
Finally, here's a link to the full Flask documentation
I am trying to put together a flask api endpoint that can take an image, drop it in a an 'uploads' folder and then perform an operation on it. The image will be sent from a reactjs front end. I have the beginnings of a python script that I know allows me to upload a photo via flask. But I want to alter it to:
lose the front end upload option instead giving me just the endpoint to upload the image
set it up to run a python script on that image once it lands in the uploads folder that extracts text
I've put below some of the pieces I have so far:
reactjs
#just the piece where i am sending an image to flask
fileUploadHandler =() => {
const fd = new FormData();
fd.append('image', this.state.selectedFile, this.state.selectedFile.name)
console.log('file is uploaded')
//axios.post('my_endpoint');
}
app.py
#from https://stackoverflow.com/questions/52152464/convert-normal-python-script-to-reset-api
import sumTwoNumbers
from flask import Flask, request
from flask_restful import Resource, Api
import os
from werkzeug.utils import secure_filename
import cv2
PROJECT_HOME = os.path.dirname(os.path.realpath(__file__))
UPLOAD_FOLDER = '{}/uploads/'.format(PROJECT_HOME)
app = Flask(__name__)
api = Api(app)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
ALLOWED_EXTENSIONS = set(['jpg','png'])
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
_path = os.path.abspath("<FILE PATH>")
#uf = str(uuid.uuid4())
return redirect(url_for('index'))
return """
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
<p>%s</p>
""" % "<br>".join(os.listdir(app.config['UPLOAD_FOLDER'],))
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
imageToText.py
#script to run on the image that pulls text
import cv2
import pytesseract
import imutils
img = cv2.imread('note.PNG')
#use tesseract to convert image into strinf
text = pytesseract.image_to_string(img, lang='eng')
print(text)
Here I have an excel to pdf conversion script. How can I modify it to act as a REST API?
import os
import comtypes.client
SOURCE_DIR = 'D:/projects/python'
TARGET_DIR = 'D:/projects/python'
app = comtypes.client.CreateObject('Excel.Application')
app.Visible = False
infile = os.path.join(os.path.abspath(SOURCE_DIR), 'ratesheet.xlsx')
outfile = os.path.join(os.path.abspath(TARGET_DIR), 'ratesheet.pdf')
doc = app.Workbooks.Open(infile)
doc.ExportAsFixedFormat(0, outfile, 1, 0)
doc.Close()
app.Quit()
You can use Python's Flask lightweight Rest Framework to make your program accessible for REST Calls. Check this tutorial: http://flask.pocoo.org/docs/1.0/tutorial/
There you can simply get the file input in POST format and once the file is converted send a downloadable link to the end user. You have to tweak this code I wrote with a friend for similar purposes:
import os
from flask import Flask, request, redirect, url_for
from werkzeug import secure_filename
PROJECT_HOME = os.path.dirname(os.path.realpath(__file__))
UPLOAD_FOLDER = '{}/uploads/'.format(PROJECT_HOME)
ALLOWED_EXTENSIONS = set(['txt','pdf', 'vcf'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
_path = os.path.abspath("<FILE PATH>")
uf = str(uuid.uuid4())
# DO YOUR AMAZING STUFF HERE
return redirect(url_for('index'))
return """
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
<p>%s</p>
""" % "<br>".join(os.listdir(app.config['UPLOAD_FOLDER'],))
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5001, debug=True)
I want to delete a file after the user downloaded a file which was created by the flask app.
For doing so I found this answer on SO which did not work as expected and raised an error telling that after_this_request is not defined.
Due to that I had a deeper look into Flask's documentation providing a sample snippet about how to use that method. So, I extended my code by defining a after_this_request function as shown in the sample snippet.
Executing the code resp. running the server works as expected. However, the file is not removed because #after_this_request is not called which is obvious since After request ... is not printed to Flask's output in the terminal:
#!/usr/bin/env python3
# coding: utf-8
import os
from operator import itemgetter
from flask import Flask, request, redirect, url_for, send_from_directory, g
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '.'
ALLOWED_EXTENSIONS = set(['csv', 'xlsx', 'xls'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
def after_this_request(func):
if not hasattr(g, 'call_after_request'):
g.call_after_request = []
g.call_after_request.append(func)
return func
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
#after_this_request
def remove_file(response):
print('After request ...')
os.remove(filepath)
return response
return send_from_directory('.', filename=filepath, as_attachment=True)
return '''
<!doctype html>
<title>Upload a file</title>
<h1>Uplaod new file</h1>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
'''
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=True)
What do I miss here? How can I ensure calling the function following to the #after_this_request decorator in order to delete the file after it was downloaded by the user?
Note: Using Flask version 0.11.1
Just import after_this_request from flask, you don't need to modify after_request or create a hook.
from flask import after_this_request
#after_this_request
def remove_file(response):
print('After request ...')
os.remove(filepath)
return response
Make sure to import the decorator from flask.after_this_request. The decorator is new in Flask 0.9.
If you are using Flask 0.8 or older, then there is no specific after this request functionality. There is only a after every request hook, which is what the snippet coopts to handle per-request call-backs.
So unless you are using Flask 0.9 or newer you need to implement the documented hook yourself:
#app.after_request
def per_request_callbacks(response):
for func in getattr(g, 'call_after_request', ()):
response = func(response)
return response
So that hook is run after each and every request, and looks for a list of hooks to call in g.call_after_request. The after_this_request decorator registers a function there.