Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python and Flask - Trying to have a function return a file content

I am struggling to return a file content back to the user. Have a Flask code that receives a txt file from an user, then the Python function transform() is called in order to parse the infile, both codes are doing the job.

The issue is happening when I am trying to send (return) the new file (outfile) back to the user, the Flask code for that is also working OK. But I don´t know how to have this Python transform function() "return" that file content, have tested several options already.

Following more details:

def transform(filename):

    with open(os.path.join(app.config['UPLOAD_FOLDER'],filename), "r") as infile:
        with open(os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_1st.txt'), "w") as file_parsed_1st:

            p = CiscoConfParse(infile)
            ''' 
            parsing the file uploaded by the user and 
            generating the result in a new file(file_parsed_1st.txt)  
            that is working OK
            '''

    with open (os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_1st.txt'), "r") as file_parsed_2nd:
        with open(os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_2nd.txt'), "w") as outfile:
            '''
            file_parsed_1st.txt is a temp file, then it creates a new file (file_parsed_2nd.txt)
            That part is also working OK, the new file (file_parsed_2nd.txt) 
            has the results I want after all the parsing;
            Now I want this new file(file_parsed_2nd.txt) to "return" to the user
            '''

    #Editing -  
    #Here is where I was having a hard time, and that now is Working OK
    #using the follwing line:

        return send_file(os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_2nd.txt')) 
like image 499
Fabiano Lima Avatar asked Apr 29 '26 08:04

Fabiano Lima


1 Answers

You do need to use the flask.send_file() callable to produce a proper response, but need to pass in a filename or a file object that isn't already closed or about to be closed. So passing in the full path would do:

return send_file(os.path.join(app.config['UPLOAD_FOLDER'], 'file_parsed_2nd.txt'))

When you pass in a file object you cannot use the with statement, as it'll close the file object the moment you return from your view; it'll only be actually read when the response object is processed as a WSGI response, outside of your view function.

You may want to pass in a attachment_filename parameter if you want to suggest a filename to the browser to save the file as; it'll also help determine the mimetype. You also may want to specify the mimetype explicitly, using the mimetype parameter.

You could also use the flask.send_from_directory() function; it does the same but takes a filename and a directory:

return send_from_directory(app.config['UPLOAD_FOLDER'], 'file_parsed_2nd.txt')

The same caveat about a mimetype applies; for .txt the default mimetype would be text/plain. The function essentially joins the directory and filename (with flask.safe_join() which applies additional safety checks to prevent breaking out of the directory using .. constructs) and passes that on to flask.send_file().

like image 180
Martijn Pieters Avatar answered Apr 30 '26 22:04

Martijn Pieters



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!