Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove file after Flask serves it

Tags:

python

csv

flask

I have a Flask view that generates data and saves it as a CSV file with Pandas, then displays the data. A second view serves the generated file. I want to remove the file after it is downloaded. My current code raises a permission error, maybe because after_request deletes the file before it is served with send_from_directory. How can I delete a file after serving it?

def process_data(data)
    tempname = str(uuid4()) + '.csv'
    data['text'].to_csv('samo/static/temp/{}'.format(tempname))
    return file

@projects.route('/getcsv/<file>')
def getcsv(file):
    @after_this_request
    def cleanup(response):
        os.remove('samo/static/temp/' + file)
        return response

    return send_from_directory(directory=cwd + '/samo/static/temp/', filename=file, as_attachment=True)
like image 588
cnstlungu Avatar asked Nov 28 '16 20:11

cnstlungu


People also ask

How do you delete a file after using Python?

Using the os module in python To use the os module to delete a file, we import it, then use the remove() function provided by the module to delete the file. It takes the file path as a parameter. You can not just delete a file but also a directory using the os module.

Where does flask save uploaded files?

The server-side flask script fetches the file from the request object using request. files[] Object. On successfully uploading the file, it is saved to the desired location on the server. The uploaded file is saved to the temporary directory of the server for a while before it is saved to some desired location.


1 Answers

after_request runs after the view returns but before the response is sent. Sending a file may use a streaming response; if you delete it before it's read fully you can run into errors.

This is mostly an issue on Windows, other platforms can mark a file deleted and keep it around until it not being accessed. However, it may still be useful to only delete the file once you're sure it's been sent, regardless of platform.

Read the file into memory and serve it, so that's it's not being read when you delete it later. In case the file is too big to read into memory, use a generator to serve it then delete it.

@app.route('/download_and_remove/<filename>')
def download_and_remove(filename):
    path = os.path.join(current_app.instance_path, filename)

    def generate():
        with open(path) as f:
            yield from f

        os.remove(path)

    r = current_app.response_class(generate(), mimetype='text/csv')
    r.headers.set('Content-Disposition', 'attachment', filename='data.csv')
    return r
like image 135
davidism Avatar answered Sep 18 '22 19:09

davidism