Не скачиваются файлы с сервера flask
Основная идея загрузки файлов во Flask на самом деле довольно проста. В основном это работает так:
- Тег формы помечается как enctype=multipart/form-data , и в эту форму помещается .
- Приложение обращается к файлу из словаря Request.files в объекте запроса.
- Используйте метод полученного объекта файла .save() , чтобы навсегда сохранить файл где-нибудь в файловой системе.
Ведение в загрузку файлов на Flask.
Создадим простое приложение, которое загружает файл в определенную папку и отображает его пользователю. Смотрим код инициализации веб-приложения:
Зачем ограничивать разрешенные к загрузке расширения файлов? Если сервер напрямую будет отправлять загруженные данные клиенту, то могут быть проблемы с XSS. Например загруженные HTML файлы могут содержать вредоносный JavaScript или если на сервере установлен php интерпретатор, то загруженные файлы php, с вредоносным кодом могут выполнится и т.д. Ограничивая разрешенные к загрузке расширения, мы оберегаем себя от разного рода неприятностей.
Далее напишем функции, которые проверяют, допустимо ли расширение, загружают файл и перенаправляют пользователя на URL-адрес загруженного файла:
Так что же на самом деле делает функция secure_filename() ? Проблема в том, что существует принцип, называемый "никогда не доверяйте вводу пользователя". Это также верно для имени загруженного файла. Все отправленные данные формы могут быть подделаны, а имена файлов могут быть опасными. Просто запомните: всегда используйте эту функцию для защиты имени файла перед сохранением его непосредственно в файловой системе.
Какие могут быть проблемы, если не использовать secure_filename() ? Представьте, что кто-то отправит следующую информацию в качестве имени файла в ваше приложение:
Предполагая, что вложенность ../ правильная, и Flask присоединит к нему папку UPLOAD_FOLDER , то пользователь сайта может иметь возможность изменить файл в файловой системе сервера, который он или она не должны изменять. Это действительно требует некоторых знаний о том, как выглядит приложение, но поверьте, хакеры терпеливы.
Посмотрим, как работает функция secure_filename() :
Теперь определим функцию-представление download_file для обслуживания файлов в папке загрузки по его имени. Функция url_for('download_file', name=name) генерирует URL-адреса для скачивания.
Ответы 2
Убедитесь, что вы достигли оператора «если разрешено (имя файла):». Возможно, запрос закончится раньше.
даже если я закомментирую if-Statement, файл не будет загружен.
Измените свою переменную folder на это:
И поменяйте свой file.save на это:
Думаю, это решит вашу проблему.
К сожалению, это не решает мою проблему. Он создает папку «instance» с подпапкой «uploads». Когда я загружаю файл на localhost, он не появляется в папке загрузок.
Вы имеете в виду папку выгрузки в папку экземпляра? Потому что его нужно загрузить. Есть ошибка или предупреждение?
Он никуда не сохраняет загруженный файл. Я не могу его найти. Никаких ошибок, только банальные предупреждения. Я не понимаю
Вы можете распечатать os.path.join(folder, secure_filename(file.name)) ?
как я это сделал? Я имею в виду, где мне поместить заявление о печати?
Непосредственно перед вашей функцией file.save . Я сказал это, чтобы проверить ваш каталог.
Нет вывода . ничего не печатается
В качестве последней надежды создайте папку с именем uploads рядом с вашей папкой и измените функцию сохранения на эту: file.save('uploads'+os.sep+secure_filename(file.name))
И вы поместили оператор печати прямо над функцией file.save , верно? Если он не распечатывает вывод, это означает, что оператор заблокировал file.save .
Не знаю, что менял (ничего не думаю), но сейчас все работает. Спасибо!
Я думал прямо сейчас, что проблема была в разрешенной функции. Но если он работает прямо сейчас, нет проблем.
Форма загрузки файлов.
Чтобы действительно загрузить файлы, необходимо правильно настроить форму. Форма, которая загружает файлы, должна иметь свой метод, установленный в POST , и свой тип enctype , установленный в multipart/form-data . Если метод формы настроен на GET , то загрузка вообще не будет работать, а если не установить enctype , то будет передано только имя файла.
Само поле должно быть .
Похожие вопросы
Patebin api возвращает «неверный запрос API, используйте запрос POST, а не GET» для request.post в Python?
Находите ответы на сложные технические вопросы по программированию, с которыми сталкиваются инженеры по всему миру в своей ежедневной практике на сайте RedDeveloper.
Я использую Flask с send_file() , чтобы люди скачивали файл с сервера.
Мой текущий код выглядит следующим образом:
Единственная причина, по которой я добавил .f137.mp4 , заключается в том, что я использую AWS C9 в качестве своей онлайн-среды IDE, и я не могу установить FFMPEG для объединения аудио и видео в Amazon Linux. Однако проблема не в этом. Проблема в том, что он не отправляет запрос на загрузку.
Вот вывод консоли:
Любая помощь приветствуется. Спасибо!
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ.
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это.
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и.
4 Answers 4
You need to make sure that the value you pass to the directory argument is an absolute path, corrected for the current location of your application.
The best way to do this is to configure UPLOAD_FOLDER as a relative path (no leading slash), then make it absolute by prepending current_app.root_path :
It is important to reiterate that UPLOAD_FOLDER must be relative for this to work, e.g. not start with a / .
A relative path could work but relies too much on the current working directory being set to the place where your Flask code lives. This may not always be the case.
Делал тестовую страницу, путь ставил без БД. Результат: файл не найден.
На что думаю, так это на то, что картинки лежать в static/images. Значит, flask знает корень (ну или у него по умолчанию). Медиа файлы записываются в другую директорию рядом. Надо что-то в конфиг писать?
Как flask отдаёт данные? Что почитать?
Вообще статику обычно отдают каким-нить nginx.
Блиин, его поднимать на домашнем ноуте? Я так мимоходом читал, что nginx скармливают пути, да думал, что кроме него есть методы.
Я не туда смотрю. Утро. Вот код, ссылающийся на картинку:
вот код на файл:
В браузере светит правильный путь:
И пишет - 404 Not found.
Я хз, но для разработки, думаю, что не нужно nginx. Возможно надо использовать send_from_directory(). Бог его знает. Поспать надо. И спасибо.
Создай репу на гитхабе со всем кодом, и кинь сюда - люди помогут. А лучше найди на гитхабе уже готовый проект с uplod file flask в поиске гитхаба, короче, расширяй границы сознания)
Ч, конечно, слегка в шоке. Чего так сложно? Перечитав документацию нашел ссылку на send_from_directory(). Это ужос.
Ну так-то он прав, на dev сервере удобно, чтобы оно статику оттадавало само.
Да. У меня так (работает и в runserver и на проде с uwsgi/nginx):
Спасибо. Похоже и у меня написано. Но есть детали ;( Может, поможешь:
Эта функция «send_from_directory()» не хочет обрабатывать моё имя файла. Я прочел, что в целях безопасности(".." и «/»), а в имени я хранил кусочек пути.
Как передаёшь путь?
Как хранишь файлы, чтобы не дублировались и т.д.? Если я храню файлы по их хешу, я могу конечно и построить url, но думал, что зачем вызывать функцию, когда при сохранении файла на сервер, я генерирую и создаю сразу путь по 2-3 символам имени хеша, записываю его в базу. Вот с таким именем эта функция и не дружит :(. В нете инфы практически нет.
Никак, все файлы лежат в одном каталоге (audio). У меня их немного.
Как хранишь файлы, чтобы не дублировались и т.д.?
Генерирую уникальное имя. В базе храню исходное имя и то, под каким файл лежит на диске:
Спасибо. А вот эта строка обязательна? current_app.config['UPLOAD_PATH']? Я вот просто создал config.py. С него экспорт (настройки БД, пути, разрешения и т.д.). Я просто не знаю, может эта опция даёт гибкость?
За uuid отдельная благодарность, не знал. Я делал hash файла через md5 (тот еще геморрой, как показала практика, так как надо было читать блоками и заметно проседала производительность (ну и я криворукий)).
По идее не обязательна. Но если ты хранишь пути в конфиге, то как считываешь их во views.py? ИМХО единственно правильный способ через current_app, т.е. прямое обращение к инстансу приложения.
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ.
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это.
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и.
Содержание:
Ответы 3
Вам нужно для return результат send_file :
К сожалению, это затруднит вам «очистку» после отправки файла, поэтому вы, вероятно, захотите сделать это в рамках планового обслуживания (например, запустить задание cron для удаления старых загруженных файлов). См. здесь для получения дополнительной информации о проблеме.
Как сказал Роб Бричено:
You need to return the result of send_file
Таким образом, вы можете сохранить результат «flask.send_file», затем очистить, а затем вернуть результат.
Было бы намного лучше, если бы это сработало! Но разве send_file() не работает асинхронно? Как вы можете быть уверены, что os.remove() запускается после того, как здесь send_file() завершился?
Расширяя ответ @Rob Bricheno, если вам нужно очистить после запроса, вы можете создать отложенный метод, который будет выполняться после завершения запроса:
Если проблема заключается в том, что файл должен существовать даже после отправки ответа, вам нужно будет решить проблему с временным файлом. Но я предполагаю, что send_file является частью самого ответа.
Демо-версия загрузки фотографий с помощью Flask-Uploads и Flask-WTF.
Шаблон index.html необходимо поместить в папку с именем templates .
Это файл самого приложения для загрузки фотографий с помощью расширений Flask-Uploads и Flask-WTF
I'm trying to create a web app with Flask that lets a user upload a file and serve them to another user. Right now, I can upload the file to the upload_folder correctly. But I can't seem to find a way to let the user download it back.
I'm storing the name of the filename into a database.
I have a view serving the database objects. I can delete them too.
In my HTML I have:
and a download view :
But it's returning :
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
I just want to link the filename to the object and let the user download it (For every object in the same view)
For what URL does Flask return a 404 Not Found response? Have you verified that the filename in question really resides in app.config['UPLOAD_FOLDER'] ?
It does, because I have an upload forms that really did upload the file. I just can't download it. The uploading to the folder is fine. The url is : 127.0.0.1:5000/uploads/rsc_chapitre17.pdf and the file is really there !
The reason I ask is because send_from_directory() will raise a NotFound when there is no file there. So os.path.isfile(app.config['UPLOAD_FOLDER']/filename) returned false. You need to doublecheck the contents of UPLOAD_FOLDER and verify that the filename you are trying to load is really there.
It is there, changed app = Flask(name) to app = Flask(name, static_folder='uploads') and for some reasons it worked.
Python deals with the trailing slash just fine. It is the leading slash that is the issue here. You have defined an absolute path, not a relative one.
Конфигурация расширения Flask-Uploads.
Конфигурация набора загрузки хранится в приложении. Таким образом, можно использовать наборы загрузки сразу в нескольких приложениях. Используйте функцию configure_uploads() , чтобы загрузить конфигурацию для разных наборов загрузок. Функция configure_uploads() передает приложению и все наборы загрузок. Вызов configure_uploads более одного раза безопасен.
Если приложение имеет фабрику приложений, то это, именно то место где нужно настраивать расширение Flask-Uploads.
По умолчанию Flask не накладывает никаких ограничений на размер загружаемых данных. Чтобы защитить приложение, можно использовать patch_request_class() . Если вызывать patch_request_class() со вторым параметром None , то для ограничения максимального размера загружаемого файла будет использоваться параметр конфигурации MAX_CONTENT_LENGTH .
Класс patch_request_class() также второй параметр может быть числом, которое установить абсолютный предел, но он существует только по причинам обратной совместимости и не рекомендуется для использования. Кроме того, это не обязательно для Flask 0.6 или выше.
Содержание:
Наборы загрузок UploadSet .
"Набор загрузок" - это единый набор файлов какой-категории. Его необходимо объявить в коде:
После этого можно использовать метод .store() , для сохранения загруженного файла в определенную директорию, после чего извлечь путь до файла и URL-адрес для доступа к нему. Например:
Если в конфигурации указано "расположение загрузок по умолчанию" UPLOADS_DEFAULT_DEST и например, ваше приложение имеет каталог экземпляра приложения, при этом загрузки должны сохраняться в папке upload каталога экземпляра приложения, то можно быстро перенастроить папку для загрузки, передав аргумент default_dest конструктору UploadSet . Например:
Расширение для загрузки файлов Flask-Uploads.
Расширение Flask-Uploads позволяет веб-приложению гибко и эффективно обрабатывать загрузку файлов, а так же обслуживать загруженные файлы. Flask-Uploads умеет создавать различные наборы загрузок - один для вложений документов, другой для фотографий и т. д. Веб-приложение может быть настроено так, чтобы сохранять эти наборы в разных местах и генерировать для них разные URL-адреса.
Ограничение размера загружаемых файлов.
Как Flask обрабатывает загрузку? Если файлы достаточно малы, то Flask будет хранить их в памяти веб-сервера, в противном случае во временном каталоге tempfile.gettempdir() . Но как указать максимальный размер файла, после которого загрузка будет прерываться? По умолчанию Flask с радостью принимает файлы с неограниченным объемом, но такое поведение можно ограничить, установив конфигурационный ключ MAX_CONTENT_LENGTH :
Приведенный выше код ограничивает максимально допустимую полезную нагрузку до 16 мегабайт. Если передается файл большего размера, Flask вызовет исключение RequestEntityTooLarge .
Проблема сброса подключения: при использовании локального сервера разработки можно получить ошибку сброса соединения вместо ответа 413. При запуске приложения на боевом сервером WSGI, ответ о статусе будет правильный.
Параметры конфигурации расширения Flask-Uploads.
Можно гибко настроить поведение расширения Flask-Uploads прямо из конфигурации создаваемого веб-приложения.
Приведенные ниже настройки применяются для одного набора загрузок, замените FILES на имя набора (например, UPLOADED_PHOTOS_DEST ):
- UPLOADED_FILES_DEST : параметр указывает на каталог, в котором будут сохранены загруженные файлы.
- UPLOADED_FILES_URL : если есть сервер, настроенный для обслуживания файлов в этом наборе, то это URL-адрес, с которого загруженные файла набора будут общедоступны. В конце добавьте косую черту / .
- UPLOADED_FILES_ALLOW : параметр, разрешающий указанные расширения файлов.
- UPLOADED_FILES_DENY : параметр, запрещающий расширения файлов.
Чтобы сэкономить время на настройку, можно указать две настройки, которые будут применяться как настройки по умолчанию.
Так же можно установить MAX_CONTENT_LENGTH , чтобы ограничить размер загружаемых файлов.
Другие вопросы по теме
Пытался разобрать фрагментированную кодировку передачи, но это не работает, файл, который я декодировал, полностью не читается
Читайте также: