从Flask下载文件后将其删除
我目前正在使用一个小型Web界面,该界面允许不同的用户上传文件,转换他们已上传的文件以及下载转换后的文件。对于我的问题,转换的细节并不重要。
我目前正在使用flask-uploads管理上传的文件,并将它们存储在文件系统中。用户上传并转换文件后,会有各种各样漂亮的按钮可以删除该文件,因此上载文件夹不会被填满。
我认为这不是理想的选择。我真正想要的是在下载文件后立即将其删除。我希望在会话结束时删除要删除的文件。
我花了一些时间试图弄清楚该怎么做,但是我还没有成功。这似乎不是一个罕见的问题,所以我认为肯定有一些我缺少的解决方案。有没有人有办法解决吗?
回答:
有几种方法可以做到这一点。
send_file
然后立即删除(仅限Linux)
Flask有一个after_this_request
装饰器,可用于此用例:
@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)
问题是,这仅在Linux上有效(即使在删除文件后仍存在指向其的打开文件指针,该文件也可以读取)。它也不会一直有效(我听说有报道说,send_file
在Flask已经取消链接文件之前,有时不会结束对内核的调用)。它并不会阻塞Python进程来发送文件。
流文件,然后删除
理想情况下,尽管你在知道操作系统已将其流式传输到客户端后清理了文件。你可以通过以下方式来实现此目的:创建一个生成器,将生成的文件流式传输,然后将其关闭,然后通过Python将其流式传输回Python,如以下答案所示:
def download_file(filename): file_path = derive_filepath_from_filename(filename)
file_handle = open(file_path, 'r')
# This *replaces* the `remove_file` + @after_this_request code above
def stream_and_remove_file():
yield from file_handle
file_handle.close()
os.remove(file_path)
return current_app.response_class(
stream_and_remove_file(),
headers={'Content-Disposition': 'attachment', 'filename': filename}
)
这种方法很好,因为它是跨平台的。但是,这并不是灵丹妙药,因为它束缚了Python Web进程,直到将整个文件传输到客户端为止。
清理计时器
在计时器上运行另一个进程(cron
也许使用),或使用进程调度程序(例如APScheduler)并清理超出超时(例如,半小时,一周,三十天,之后它们在RDMBS中被标记为“已下载”)
这是最可靠的方法,但是需要额外的复杂性(cron,进程内调度程序,工作队列等)。
以上是 从Flask下载文件后将其删除 的全部内容, 来源链接: utcz.com/qa/435428.html