Flask-删除上传后的上传内容

时间:2014-07-07 13:58:27

标签: python flask flask-uploads

我目前正在开发一个小型网络界面,允许不同的用户上传文件,转换他们上传的文件,并下载转换后的文件。转换的详细信息对我的问题并不重要。

我目前正在使用flask-uploads来管理上传的文件,我将它们存储在文件系统中。一旦用户上传并转换文件,就会有各种漂亮的按钮来删除文件,因此上传文件夹不会填满。

我不认为这是理想的。我真正想要的是在下载文件后立即删除它们。我会满足会议结束时被删除的文件。

我花了一些时间试图弄清楚如何做到这一点,但我还没有成功。这似乎不是一个不寻常的问题,所以我认为必须有一些解决方案,我错过了。有没有人有解决方案?

4 个答案:

答案 0 :(得分:23)

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)

问题是这将only work well on Linux(如果仍然有一个打开的文件指针,即使在删除后也可以读取文件)。

答案 1 :(得分:1)

您还可以将文件存储在内存中,将其删除,然后提供您在内存中的存储空间。

例如,如果您正在提供PDF:

var yourThing = new Thing()
    .with(new PropertyA()).thenWith(new DependentPropertyOfA()) // digress a bit
    .with(new PropertyB()) // back to main thread here
    .withPieceOfLogic((parameter1, parameter2) => {define some logic here}) // so you can potentially can swap implementations as well
    .create();

(上面我只是假设它是PDF,但是如果需要,您可以get the mimetype以编程方式进行操作)

答案 2 :(得分:0)

基于@Garrett的注释,更好的方法是在删除文件时不阻止send_file。恕我直言,更好的方法是在后台将其删除,如下所示更好:

import io
import os
from flask import send_file
from multiprocessing import Process

@app.route('/download')
def download_file():
    file_path = get_path_to_your_file()

    return_data = io.BytesIO()
    with open(file_path, 'rb') as fo:
        return_data.write(fo.read())
        return_data.seek(0)    

    background_remove(file_path)

    return send_file(return_data, mimetype='application/pdf',
                     attachment_filename='download_filename.pdf')


def background_remove(path):
    task = Process(target=rm(path))
    task.start()

    
def rm(path):
    os.remove(path)

答案 3 :(得分:0)

Flask 有一个 after_request 装饰器,可以在这种情况下工作:

@app.route('/', methods=['POST'])
    def upload_file():
    uploaded_file = request.files['file']
    file = secure_filename(uploaded_file.filename)

    @app.after_request
    def delete(response):
        os.remove(file_path)
        return response

    return send_file(file_path, as_attachment=True, environ=request.environ)