There are several ways to do this.
send_file and then delete it immediately (Linux only)
Flask has an after_this_request decorator that can work for this after_this_request use:
@app.route('/files/<filename>/download') def download_file(filename): file_path = derive_filepath_from_filename(filename) file_handle = open(file_path, 'r') @after_this_request def remove_file(response): try: os.remove(file_path) file_handle.close() except Exception as error: app.logger.error("Error removing or closing downloaded file handle", error) return response return send_file(file_handle)
The problem is that this will only work on Linux (which allows you to read the file even after deletion if it still has an open file pointer to it). This also does not always work (I heard reports that sometimes send_file did not send_file a kernel call before Flask already detached the file). This does not bind the Python process to send the file, though.
Stream file then delete
Ideally, at least the file should be cleaned after you find out that the OS passed it to the client. You can do this by streaming the file back through Python by creating a generator that translates the file and then closes it, as suggested in this answer :
def download_file(filename): file_path = derive_filepath_from_filename(filename) file_handle = open(file_path, 'r')
This approach is good because it is cross-platform. However, this is not a silver bullet because it binds the Python web process until the entire file is transferred to the client.
Get out of the timer
Start another timer process (possibly using cron ) or use an in- process scheduler such as APScheduler and clear the files that were on disk at a temporary location outside of your waiting time (for example, half an hour, one week, thirty days after of how they were marked as "loaded" in RDMBS)
This is the most reliable way, but it requires additional complexity (cron, scheduler in progress, work queue, etc.)
Sean vieira
source share