Issue
I created a small web app that can upload and download files (pdf, txt, docx) to a sqlite3 database. It uses Flask as its backend framework. When I press the download button, the download route is called and everything seems fine, but the download tab in the browser doesn’t open and nothing is downloaded.
The print statement logs valid filenames to the terminal. Where did I go wrong?
HTML snippet for upload and download:
{% block main %}
Data Bank
download
Date
Leschen
{File % in % current_user.files}
{{file.filename}}
{% end for %}
{% End Block %}
{% block script %}
{%End Block%}
JavaScript used:
function download_files(fileid) {
fetch("/download", {
method: "POST",
Body: JSON.stringify({ File ID: File ID }),
}))
}
Flask code:
@files.route("/download" , methods=["POST"])
@login is needed
Def Download():
file = json.loads(request.data)
fileID = file["fileid"]
File = Upload.query.filter_by(id=fileID).first()
For files:
If file.user_id == current_user.id:
print(f"Downloaded file {file.filename}!" )
return send_file(BytesIO(file.data), download_name=file.filename,as_attachment=True )
Edit 1 :
Upload your code
html:
Datei Hokladen
Unterstütze Dateiformate: .doc .docx .pdf .txt .odt
Python:
@files.route("/upload", methods=["GET", "POST"])
@login is needed
diff upload():
If request.method == 'POST':
allowed_files = [".doc",".docx",".pdf",".txt",".odt"]
file = request.files['file']
file_ext = os.path.splitext(file.filename)[1]
If file_ext is not in allowed_files:
flash(f"Dateiformat {file_ext} nicht unterstütt! ",category="error")
return render_template("drive.html")
elif not file.filename == '':
upload = upload (filename=secure_filename(file.filename), data=file.read(), date=datetime.datetime.now(), user_id=current_user.id)
db.session.add(upload)
Decibel. session. commit()
flash(f"Dateien Hochgeladen ! ",category="success")
return redirect(url_for("views.drive"))
other than that:
flash(f"Ungültiger Dateiname Dateiname: {file.filename} ! ",category="error")
return render_template("drive.html")
other than that:
return render_template("drive.html")
I have verified that the correct files are sent to the download function. Also, that the file exists and that the function executes up to the return statement.
I checked flask’s send_file documentation for mistakes in the send_file() function and checked chrome’s dev tools to see if there was a payload.
Edit 2:
I tried with the following code which works. Maybe someone can explain me the difference. From my console log, my code does exactly the same. Just get the id via javascript fetch() instead of flask root credentials.
@app.route('/download/')
def download (upload_id):
Upload = Upload.query.filter_by(id=upload_id).first()
return send_file(BytesIO(upload.data), download_name=upload.filename, as_attachment=True)
The reason I don’t use this is because I don’t know how to send the file id to flaskroot without the javascript part. Maybe someone can help me with that part.
Solution
Not a real answer to the problem but a working solution:
I changed the download route to :
@files.route('/download/<file_id>', methods=["POST"])
@login_required
def download(file_id):
if request.method == "POST":
file = Uploads.query.filter_by(id=file_id).first()
return send_file(BytesIO(file.data), download_name=file.filename, as_attachment=True)
The file gets selected by the file_id send by the html file
<form action="/download/{{file.id}}" method="post" >
<button type="submit" class="close" >
<i class="bi bi-download" style="color:black;width: 2%;height: 2%"></i>
</button>
</form>
Answered By – Revero
Answer Checked By – Marilyn (Easybugfix Volunteer)