Загрузка и загрузка файлов с помощью Flask
Я пытаюсь написать действительно просто webapp с PythonAnywhere и Flask, который позволяет пользователю загружать текстовый файл, генерирует файл csv, а затем позволяет пользователю загружать файл csv. Это не должно быть фантазией, это должно только работать. Я уже написал программу для генерации csv из txt-файла на диске.
прямо сейчас, моя функция открывает файл на диске с:
with open(INPUTFILE, "r") as fname:
и пишет csv с:
with open(OUTPUTFILE, 'w') as fname:
С INPUTFILE и OUTPUTFILE являются строками имени файла.
было бы лучше для меня обрабатывать файлы как объекты, возвращаемые колбой/html каким-то образом?
Я не знаю, как это делать. Как я должен структурировать эту программу? Сколько шаблонов HTML мне нужно? Я бы предпочел работать над файлами без сохранения их в любом месте, но если мне нужно сохранить их в каталоге PythonAnywhere, я мог бы. Как я могу это сделать?
2 ответов
PythonAnywhere dev здесь. Это хороший вопрос о колбе и веб-разработке в целом, а не конкретно для нашей системы, поэтому я постараюсь дать общий ответ без чего-либо конкретного для нас: -)
есть несколько вещей, которые мне нужно знать, чтобы дать окончательный ответ на ваш вопрос, поэтому я начну с перечисления предположений, которые я делаю-оставьте мне комментарий, если я ошибаюсь с любым из них, и я обновлю ответ соответственно.
- я предполагаю, что файлы, которые вы загружаете, не огромны и могут поместиться в разумный объем памяти-скажем, меньше мегабайта.
- я предполагаю, что программа, которую вы уже написали для создания CSV из текстового файла, находится в Python, и что она имеет (или, возможно, более вероятно, может быть легко изменена) функцию, которая принимает строку, содержащую содержимое текстового файла, и возвращает содержимое, которое нужно для записи в CSV.
если оба эти случая, то лучший способ структурировать приложение колбы было бы обрабатывать все внутри колбы. Пример кода стоит тысячи слов, поэтому вот простой, который я собрал, который позволяет пользователю загружать текстовый файл, запускает его через функцию transform
(где функция из вашей программы преобразования будет слот в -- mine просто заменяет =
С ,
по всему файлу), и отправляет результаты обратно в браузер. есть живая версия этого приложения на 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():
file = request.files['data_file']
if not file:
return "No file"
file_contents = file.stream.read().decode("utf-8")
result = transform(file_contents)
response = make_response(result)
response.headers["Content-Disposition"] = "attachment; filename=result.csv"
return response
по поводу ваших вопросов:
- Templates: я не использовал шаблон для этого примера, потому что я хотел, чтобы все это вписывалось в один фрагмент кода. Если бы я делал это правильно, я бы поместил материал, который генерируется
form
посмотреть в шаблон, но это все. - можете ли вы сделать это, написав в файлы - да вы может, и загруженный файл может быть сохранен с помощью
save(
имя файла)
методfile
объект, который я используюstream
собственность. Но если ваши файлы довольно малы (согласно моему предположению выше), то, вероятно, имеет смысл обрабатывать их в памяти, как это делает код выше.
Я надеюсь, что все поможет, и если у вас есть какие-либо вопросы, просто оставьте комментарий.
лучше добавить
response.headers["Cache-Control"] = "must-revalidate"
response.headers["Pragma"] = "must-revalidate"
response.headers["Content-type"] = "application/csv"
Если вы не добавляете тип контента, FF 48.0 сообщил об этом как html и открыл диалог сохранения один раз для HTML, а затем для CSV. Если вы не добавляете Cache-Control, ваш результат может кэшироваться, а если вы обслуживаете активный контент, это не то, что вы хотите. Если вы используете must-revalidate без возраста, он будет эффективно служить no-cache-see здесь и здесь для объяснений.