Search code examples
pythonflaskhttpserver

Python flask app which returns list of files


I have a basic flask app which is used to get logs from pods. I want to use send_from_directory when the query is not complete. I do not want to create a zip file and list it rather I would like to list the logs files that are generated with the query.

from flask import Flask, send_from_directory
from flask import request
import http.server
import socketserver
import subprocess
import os
import sys
from urllib.parse import urlparse
from urllib.parse import parse_qs

app = Flask(__name__)
# write route for a namespace completely
@app.route('/logs')
def hello_world():
umgebung = request.args.get('umgebung', None)
product = request.args.get('product', None)
product_type = request.args.get('product_type', None)
output = (subprocess.check_output(['cmd', '/c', f'oc logs --tail=-1 -n awl-{umgebung} -l product={product},type={product_type}'])).decode();
if not output:
    output_as = (subprocess.check_output(['cmd', '/c', f'oc logs --tail=-1 -n awl-{umgebung} -l product={product},type=as'])).decode();
    output_db = (subprocess.check_output(['cmd', '/c', f'oc logs --tail=-1 -n awl-{umgebung} -l product={product},type=db'])).decode();
    output_as_file = open ("logs/output_as_log.log","w")
    output_db_file = open ("logs/output_db_log.log","w")
    output_as_file.write(output_as)
    output_db_file.write(output_db)
    path= 'logs'
    return send_from_directory(path, output_as_file,as_attachment=True) #HERE I DO NOT UNDERSTNAD WHAT SHOUDL  BE GIVEN       
output = "<br />".join(output.split("\n"))   
return output

I am creating the log files under the logs folder within the project folder. How can i display all the files in the folder log ? So that it can be downloaded with a click?

Clarification for the close Votes!!

The app should return the files from a particular folder. But the send_fron_directory is not working as expected.


Solution

  • You can list all files using os.listdir, glob.glob or the pathlib library. The result can then be output within a template.
    Then you add a new route which expects the file name as a parameter and delivers the file from the folder via send_from_directory. You can pass the name of the file as a path within a rule.
    As far as I understand you correctly, the following example should meet your requirements.

    import os
    from flask import Flask, render_template, send_from_directory
    
    app = Flask(__name__)
    
    @app.route('/logs/')
    def logs():
        filenames = os.listdir('logs')
        return render_template('logs.html', files=filenames)
    
    @app.route('/logs/<path:filename>')
    def log(filename):
        return send_from_directory(
            os.path.abspath('logs'),
            filename,
            as_attachment=True
        )
    

    The following template should be added under templates/logs.html in the application directory.

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Logfiles</title>
      </head>
      <body>
        <ul>
        {% for file in files %}
            <li><a href="{{ url_for('log', filename=file) }}">{{ file }}</a></li>
        {% endfor %}
        </ul>
      </body>
    </html>