使用Flask上传和下载文件

Use*_*996 26 python file-upload flask python-2.7 pythonanywhere

我正在尝试使用PythonAnywhere和Flask编写一个非常简单的webapp,它允许用户上传文本文件,生成csv文件,然后让用户下载csv文件.它不一定是花哨的,它只需要工作.我已经编写了从驱动器上的txt文件生成csv的程序.

现在,我的函数打开驱动器上的文件:

with open(INPUTFILE, "r") as fname:
Run Code Online (Sandbox Code Playgroud)

并编写csv:

with open(OUTPUTFILE, 'w') as fname:
Run Code Online (Sandbox Code Playgroud)

INPUTFILE和OUTPUTFILE是文件名字符串.

对于我来说,将文件作为对象进行处理会更好吗?不知怎的,这会被flask/html返回?

我不知道该怎么做.我该如何构建这个程序?我需要多少个HTML模板?我宁愿在没有将它们保存到任何地方的情况下处理文件,但如果我必须将它们保存到PythonAnywhere目录,我可以.我怎样才能做到这一点?

Gil*_*mas 32

PythonAnywhere dev在这里.这是关于瓶和一般的而不是具体到我们的系统web开发一个很好的问题,所以我会尽力给一个通用的答案没有具体的事情我们:-)

有一些事情我需要知道,以便对你的问题给出明确的答案,所以我首先列出我正在做的假设 - 如果我对他们中的任何一个错了,请给我一个评论.我会适当地更新答案.

  • 我假设您上传的文件不是很大并且可以放入合理的内存量 - 比方说,小于一兆字节.
  • 我假设您已经编写的用于从文本文件生成CSV的程序是在Python中,并且它具有(或者更可能,可能很容易更改为具有)包含字符串的字符串的函数文本文件的内容,并返回需要写入CSV的内容.

如果两者都是这种情况,那么构建Flask应用程序的最佳方法是处理Flask中的所有内容.一个代码示例值得千言万语,所以这里有一个简单的例子,我允许用户上传一个文本文件,通过一个被调用的函数运行它transform(这是转换程序中的函数插入的地方 - 我的替换=,整个文件),并将结果发送回浏览器. 这里有关于PythonAnywhere的这个应用程序的实时版本.

from flask import Flask, make_response, request

app = Flask(__name__)

def transform(text_file_contents):
    return text_file_contents.replace("=", ",")


@app.route('/')
def form():
    return """
        <html>
            <body>
                <h1>Transform a file demo</h1>

                <form action="/transform" method="post" enctype="multipart/form-data">
                    <input type="file" name="data_file" />
                    <input type="submit" />
                </form>
            </body>
        </html>
    """

@app.route('/transform', methods=["POST"])
def transform_view():
    request_file = request.files['data_file']
    if not request_file:
        return "No file"

    file_contents = request_file.stream.read().decode("utf-8")

    result = transform(file_contents)

    response = make_response(result)
    response.headers["Content-Disposition"] = "attachment; filename=result.csv"
    return response
Run Code Online (Sandbox Code Playgroud)

关于你的其他问题:

  • 模板:我没有在这个例子中使用模板,因为我希望所有这些都适合单个代码.如果我正确地执行它,那么我会将form视图生成的内容放入模板中,但这就是全部.
  • 你可以通过写入文件来做到 - 是的,你可以,并且可以使用我正在使用属性的对象上的save(文件名)方法来保存上传的文件.但是如果你的文件非常小(根据我上面的假设)那么在内存中处理它们可能比上面的代码更有意义.filestream

我希望一切都有所帮助,如果您有任何疑问,请发表评论.


小智 7

最好添加

response.headers["Cache-Control"] = "must-revalidate"
response.headers["Pragma"] = "must-revalidate"
response.headers["Content-type"] = "application/csv"
Run Code Online (Sandbox Code Playgroud)

如果您不添加内容类型,FF 48.0将其报告为html并为HTML打开一次"保存"对话框,然后为CSV打开.如果您不添加Cache-Control,您的结果可能会被缓存,如果您提供活动内容,则这不是您想要的.如果你使用must-revalidate没有年龄,它将有效地作为无缓存 - 请参阅此处此处的解释.