From the client side I am sending an image via post from form enctype=multipart/form-data, and on the server side I am saving it to a directory. All of this works locally on my computer and running flask directly with python app.py.
Here is my reference for setting up file saving:
http://flask.pocoo.org/docs/patterns/fileuploads/
On the actual production server, I am running it with Apache and mod_wsgi, which I set up according to this website:
http://flask.pocoo.org/docs/deploying/mod_wsgi/
For directory permissions I have triedchown -R 777 and chown -R www-data:www-data where the relevant Apache code for users looks like this: WSGIDaemonProcess app user=www-data group=www-data threads=5.
However, after all of this I am still not able to get the file to save. I just get a 500 HTTP error back at the point where it tries to save the file.
Here is the relevant Flask code:
UPLOAD_FOLDER = '/images/'
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route('/upload_ocr_images', methods=['GET', 'POST'])
def upload_images():
if request.method == 'POST':
files = request.files.getlist("images[]")
for file in files:
if allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('home'))
At this point I am wondering if there is something I need to be setting on the Apache side of things.
Youre using /uploads as your path.
That means you're trying to upload to a directory named /uploads at root level of your filesystem.
This is usually wrong and normally it's the error.
If you've the uploads folder under your flask application file structure, then you should create the path using app.root_path which holds the absolute application path.
Something like
file.save(os.path.join(app.root_path, '/uploads', filename))
Related
I am trying to upload and save a file to my EC2 instance so that I can do some file manipulation.
My upload looks like this:
UPLOAD_FOLDER = os.getcwd() + '/uploads'
application = Flask(__name__)
CORS(application)
application.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#application.route("/test-upload", methods=["POST"])
def test_upload():
file = request.files['file']
filename = secure_filename(file.filename)
file.save(os.path.join(application.config['UPLOAD_FOLDER'], filename))
# return redirect(url_for('download_file', name=filename))
return str(os.path.join(application.config['UPLOAD_FOLDER'], filename))
If I remove the file.save() line, then the function won't return errors. And as you can see I'm returning the path, so that will return the correct path. But, I get a 500 bad request from the server when I try and save the file.
I'm not sure what I'm missing here.
I can locally try this using postman, and this works fine. The file saves to the right location. I do have file size for EC2 enabled to be 100MB, but I am testing with a 50 Byte file so size can't be the issue. I know the file is being uploaded to the EC2 web server for sure.
I'm having a problem with my project on Heroku, when I download a video from Youtube on localhost I used a code that takes the user's name and puts it in the Donwload directory, but in Heroku it doesn't put it there, I suspect it is with some problem when it comes to finding the director's place
#app.route('/', methods=['POST'])
def getvalue():
if request.method == 'POST':
name = request.form['url']
try:
url = name
youtube = pytube.YouTube(url)
video = youtube.streams.get_highest_resolution()
audio = youtube.streams.get_audio_only()
video_path = r'C:/Users/' + getpass.getuser() + '/Downloads/Youtube_Download'
audio_path = r'C:/Users/' + getpass.getuser() + '/Downloads/Youtube_Download/Audio'
if not os.path.exists(video_path):
os.makedirs(video_path)
os.makedirs(audio_path)
video.download(video_path)
audio.download(audio_path)
return render_template('index.html')
The problem is that there's no `C:/Users/' in the Heroku Dyno, since is a Linux environment.
The folder structure there will match your project folder structure.
But I don't actually recommend store any user data inside the Heroku Dyno since will be erased every time you restart the app (e.g. when deploying a new version)
You can use a Storage Bucket like Amazon S3 for this instead.
This is the full error we receive when running the flask application in the browser.
"Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application."
I've done some research and have already attempted to link the folder with the
app = Flask(__name__, template_folder='/templates') assignment.
Here is my directory and debug logs. Any insight would be appreciated.
Directory
Logs
try it app = Flask(__name__, template_folder='templates')
Your code needs some changes. First of all, try using
render_template('prediction.html')
instead of
render_template('templates/prediction.html')
as Flasks already looks at templates folder (which in this case means that it will look for a folder 'templates' inside the folder 'templates')
If this doesn't work, try the same but when you declare the folder do it by:
app = Flask(__name__, template_folder='/templates')
(with '/' before templates)
and not your current
app = Flask(__name__, template_folder='templates')
If nothing of the above works, just the same solutions, without declaring template_folder at all, as by default Flask looks in the folder named 'templates'
I have a flask app where a user uploads files to an upload folder. Then I want to take those files and read them into pandas dataframes for further processing. The process works fine using app.run() on my localhost. I am trying to get it to work on aws with mod_wsgi and apache.
#app.route('/uploader', methods=['POST'])
def upload_file():
if request.method == 'POST':
filenames=[]
uploaded_files = request.files.getlist("file[]")
file.save(os.path.join(app.root_path,app.config['UPLOAD_FOLDER'], filename))
filenames.append(filename)
plotfiles=parse_all(filenames)
def parse_all(filenames):
folder_path=os.path.join(app.root_path, app.config['UPLOAD_FOLDER'])
for f in filenames:
f=send_from_directory(folder_path,filename))
excel_file=pandas.ExcelFile(f)
#do more stuff
I get the error ValueError: Must explicitly set engine if not passing in buffer or path for io.
The file is uploaded to the upload folder correctly but obviously not fetched correctly into the f variable. The type of f is <class 'flask.wrappers.Response'> and f.__dict__ returns
{'_on_close': [], 'response': [], 'headers': Headers([('X-Sendfile', u'/var/www/html/cluster_app/data/filename.xlsx'), ('Content-Length', u'82668'), ('Content-Type', u'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'), ('Cache-Control', u'public, max-age=43200'), ('Expires', u'Tue, 07 Jun 2016 22:59:11 GMT'), ('ETag', u'"1465297151.54-82668-755509703"')]), '_status_code': 200, '_status': '200 OK', 'direct_passthrough': True}
When running on my localhost on my machine there was a .file attribute in the response, now response is empty. Printing folder_path gives /var/www/html/cluster_app/data which is the uploads folder.
I'm very green on flask/wsgi/apache. Would really appreciate some advice on how to access the file system in my code.
Hi I suggest you check the flask documentation about upload files here and later re-check your code.
Instead of
f=send_from_directory(folder_path,filename))
I use
f = open(os.path.join(app.root_path, app.config['UPLOAD_FOLDER'], filename))
to open the file. I just assumed send_from_directory would work as it does when I used flask app.run() on my localhost. I'd still like to know why send_from_directory does not work.
I have a flask (0.10.1) app running on a Debian Jessie VPS and powered by nginx (1.6.2). The app is working fine but I have a problem on a specific route I added recently.
The route is intended for downloading .xml files.
It is dynamic to tell the directory and the file name:
#app.route('/backups/<dir_key>/<filename>')
And it registers a function based on the flask send_from_directory function:
def backups(dir_key,filename):
directory = os.path.join(app.config['BACKUPXML_FOLDER'], dir_key)
return send_from_directory(directory, filename, as_attachment=True)
The route is generated thanks to the flask url_for function, and returned to the frontend:
return jsonify({
'backupFileUrl': url_for('backups', dir_key=dir_key, filename = filename, _external=True)
})
where it is stored in an AngularJS variable:
$scope.backupFileUrl = response.backupFileUrl;
And finally included in a <a> tag for download :
<a class="btn btn-primary"
ng-show="sessionDownload"
ng-href="{{ backupFileUrl }}" target="_blank">
<span class="glyphicon glyphicon-save"></span> Télécharger </a>
But when I click on the button, I get the following error :
What is weird to is that :
The download is properly triggered when the app is powered by a small Python server on a local Windows machine.
I have a route intended for downloads of .xlsx files which is actually working, and both on a local Windows machine and on the Jessie VPS.
Someone see how I can define the route to make it work ?
Here is the api architecture if needed :
api/app.py
import sys
sys.path.append('../')
from flask_script import Server, Manager
from kosapp import app, db
manager = Manager(app)
if __name__ == '__main__':
manager.run()
api/config.py
from os.path import abspath, dirname, join
import tempfile
basedir = dirname(abspath(__file__))
BASEDIR = dirname(abspath(__file__))
DEBUG = True
REPORTS_FOLDER = '/tmp/reports'
# on local machine
# REPORTS_FOLDER = os.path.join(tempfile.gettempdir(), 'reports')
BACKUPXML_FOLDER = '/tmp/backups'
# on local machine
# BACKUPXML_FOLDER = os.path.join(tempfile.gettempdir(), 'backups')
api/kosapp/__init__.py
from flask import Flask
app = Flask(__name__)
app.url_map.strict_slashes = False
app.config.from_object('config')
from kosapp import views
api/kosapp/views.py
import os
from flask import send_file, jsonify, request, render_template, send_from_directory
from kosapp import app
#app.route('/reports/<dir_key>/<filename>')
def reports(dir_key, filename):
directory = os.path.join(app.config['REPORTS_FOLDER'], dir_key)
return send_from_directory(directory, filename)
#app.route('/backups/<dir_key>/<filename>')
def backups(dir_key,filename):
directory = os.path.join(app.config['BACKUPXML_FOLDER'], dir_key)
return send_from_directory(directory, filename, as_attachment=True)
As a note, the route '/reports/<dir_key>/<filename>' is intended for downloading .xlsx file and works fine.
Did you remember to reload the app on the server? That's usually the problem if i get different results on my development computer and the web server.
For instance, if you deployed with gunicorn, you would have to restart gunicorn so the server would know about the changes to your code.