Flask Download a File - python

I'm trying to create a web app with Flask that lets a user upload a file and serve them to another user. Right now, I can upload the file to the upload_folder correctly. But I can't seem to find a way to let the user download it back.
I'm storing the name of the filename into a database.
I have a view serving the database objects. I can delete them too.
#app.route('/dashboard', methods=['GET', 'POST'])
def dashboard():
problemes = Probleme.query.all()
if 'user' not in session:
return redirect(url_for('login'))
if request.method == 'POST':
delete = Probleme.query.filter_by(id=request.form['del_button']).first()
db.session.delete(delete)
db.session.commit()
return redirect(url_for('dashboard'))
return render_template('dashboard.html', problemes=problemes)
In my HTML I have:
<td>Facture</td>
and a download view :
#app.route('/uploads/<path:filename>', methods=['GET', 'POST'])
def download(filename):
return send_from_directory(directory=app.config['UPLOAD_FOLDER'], filename=filename)
But it's returning :
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
I just want to link the filename to the object and let the user download it (For every object in the same view)

You need to make sure that the value you pass to the directory argument is an absolute path, corrected for the current location of your application.
The best way to do this is to configure UPLOAD_FOLDER as a relative path (no leading slash), then make it absolute by prepending current_app.root_path:
#app.route('/uploads/<path:filename>', methods=['GET', 'POST'])
def download(filename):
uploads = os.path.join(current_app.root_path, app.config['UPLOAD_FOLDER'])
return send_from_directory(directory=uploads, filename=filename)
It is important to reiterate that UPLOAD_FOLDER must be relative for this to work, e.g. not start with a /.
A relative path could work but relies too much on the current working directory being set to the place where your Flask code lives. This may not always be the case.

To download file on flask call. File name is Examples.pdf
When I am hitting 127.0.0.1:5000/download it should get
download.
Example:
from flask import Flask
from flask import send_file
app = Flask(__name__)
#app.route('/download')
def downloadFile ():
#For windows you need to use drive name [ex: F:/Example.pdf]
path = "/Examples.pdf"
return send_file(path, as_attachment=True)
if __name__ == '__main__':
app.run(port=5000,debug=True)

I was also developing a similar application. I was also getting not found error even though the file was there. This solve my problem. I mention my download folder in 'static_folder':
app = Flask(__name__,static_folder='pdf')
My code for the download is as follows:
#app.route('/pdf/<path:filename>', methods=['GET', 'POST'])
def download(filename):
return send_from_directory(directory='pdf', filename=filename)
This is how I am calling my file from html.
<a class="label label-primary" href=/pdf/{{ post.hashVal }}.pdf target="_blank" style="margin-right: 5px;">Download pdf </a>
<a class="label label-primary" href=/pdf/{{ post.hashVal }}.png target="_blank" style="margin-right: 5px;">Download png </a>

#HTML Code
<ul>
{% for file in files %}
<li> {{ file }}</li>
{% endfor %}
</ul>
#Python Code
from flask import send_from_directory
app.config['UPLOAD_FOLDER']='logs'
#app.route('/uploads/<path:filename>', methods=['GET', 'POST'])
def download(filename):
print(app.root_path)
full_path = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'])
print(full_path)
return send_from_directory(full_path, filename)

Related

Error when trying to connect to flask via localhost

I can across a script on github that send a Post request using flask.
I am trying run the script to establish a connection on my local host. But I get the below response
The method is not allowed for the requested URL.
#app.route('/', methods = ['POST'])
def index():
if 'file' not in request.files:
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a 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)
warped = transform_file(file)
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
if __name__ == '__main__':
app.run(host='127.0.0.1', threaded=True)
you are trying to have only a root i.e "/" in your route.
Can you try with a site, something like below:
#app.route('/', methods=['GET', 'POST'])
First of all it's because you do not have a GET method for the route: / address but only POST and that's the reason why Flask displays that error.
Definitely you should have a return statment at the end of function with either html code as #CoderRambo wrote in the comment or using render_template function pointing html file inside the templates folder.
Also if your going to use:
#app.route('/', methods=['GET', 'POST'])
you should add an if statment if request.method == 'POST': beforehand that partif 'file' not in request.files: - that would handle the post request and in else block have the return statment that will display the page onto which your going to enter data you'd like to post. As Flask's documention shows https://flask.palletsprojects.com/en/1.1.x/quickstart/:
Hope I helped.
Cheers

Can't get other files uploaded [python flask] with html

The problem is i am able to upload file which are in the same directory as main.py but I am unable to upload other files which are not in the same folder of main.py, suppose - main.py is in c:\users\prabhat\upload\ and the file i am uploading the file is also in c:\users\prabhat\upload\ directory, but if there is file in c:\desktop\B.xlsx then if i upload, then it shows Error, file not found.
how an i resolve this??
index.html code
<form class="" action="data" method="post">
<input type="file" name="upload-file" value="">
<input type="submit" name="" value="Submit">
</form>
main.py
from flask import Flask, render_template, request
import pandas as pd
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
return render_template('index.html')
#app.route('/data', methods=['GET', 'POST'])
def data():
if request.method == 'POST':
file = request.form['upload-file']
return '''
successfully Done!
'''
if __name__ == '__main__':
app.run(debug=True)
You don't access files uploaded through flask via request.form but rather through request.files. This should get you a valid file handle:
if request.method == 'POST':
file = request.files['upload-file']
See https://flask.palletsprojects.com/en/2.2.x/patterns/fileuploads/ for more info.
Try file = request.files['upload-file'] instead of request.form, and I guess you want to save it to the server, do it with file.save("path/to/your/folder/filename.extension")

Uploading and Processing files with Flask Rest API

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

werkzeug.routing.BuildError with Flask -- trying to build a very simple webapp

I'm trying to develop a simple webapp that prompts the user for their address, requests forecast information from the NWS through their API, and prints out the results, but I'm running into some issues tying together the HTML and the Python script. I'm still new to programming in general and this is all a very rough copy at the moment, here's the relevant code:
weather.py:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
return render_template('weather.html')
#app.route('/forecast', methods=['GET', 'POST'])
def forecast():
if request.method == 'POST':
location = request.form['address']
# gets the weather information
return render_template('forecast.html', varying_forecast = forecast, wfo = wfo_info)
if __name__ == '__main__':
app.run(debug=True)
weather.html:
<form action="{{ url_for('forecast') }}" method="post">
Enter your address here: <input type="text" name="address"><br>
<input type="submit" name="submit" value="Get My Forecast!"><br>
</form>
When I try to go to 127.0.0.1:5000 I receive this error: "werkzeug.routing.BuildError: Could not build url for endpoint 'forecast'. Did you mean 'home' instead?" To the best of my knowledge this error occurs when url_for fails to find a route, but given that the forecast function does exist I'm confused where the error is coming from. Even after commenting out the form tag in the HTML the error persists. I tried getting rid of the "wfo" and "varying_forecast" in the return statement but that also didn't do anything. The only way to fix it is by setting the url_for of the action of the form to home, but I don't see any way to run the code in there and return the forecast information, considering it's already returning the home page. I'm having trouble understanding why it fails to display the weather.html page as written.

How to fix 405 Method Not Allowed in forms, using Blueprint in Flask

I have a file upload form in HTML, which should be used to upload and save to a static folder. The problem is that it works fine in a simple Flask app, but it just doesn't work using Blueprint templates.
I have tried several different ways of making this work. When I use "url_for", the page doesn't even load (werkzeug.routing.BuildError: Could not build url for endpoint 'upload'. Did you mean 'forms_blueprint.upload' instead?).
But when I change "url_for" to "form_upload.html", the result is always that the method is not allowed.
All thoughts are appreciated.
routes.py:
UPLOAD_FOLDER = '/home/juliosouto/flask-gentelella/app/uploaded_files/'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#blueprint.route('/<template>', methods = ['GET', 'POST'])
#login_required
def route_template(template):
return render_template('form_upload' + '.html')
#blueprint.route('/upload', methods=['POST','GET'])
def upload():
file = request.files['file']
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
form_upload.html:
<form action ="{{ url_for('upload') }}" class= "dropzone" name="file" method = "POST" enctype = "multipart/form-data"></form>
I need the file to be saved to a static folder.
When I use "url_for", the page doesn't even load (werkzeug.routing.BuildError: Could not build url for endpoint 'upload'. Did you mean 'forms_blueprint.upload' instead?).
This means exactly what it says. when you build the URL you need to do it as follows:
{{ url_for('forms_blueprint.upload') }}
Also, as #gittert correctly states, your upload route returns nothing.
This should render a template, or return a redirect to someplace else.

Categories

Resources