[FIXED] flask send_files() doenst open download tab

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

{File % in % current_user.files} {% end for %}
download Date Leschen
  • {{file.filename}}
  • {% 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)

    Leave a Reply

    (*) Required, Your email will not be published