Как отправить запрос на публикацию файла python

Обновлено: 21.11.2024

Если вам нужно загрузить большое видео, иногда сервер, на который вы загружаете, не принимает его одним запросом. На разных серверах разные лимиты. Для api.video вы можете загрузить видеофайл размером до 199 МБ, прежде чем ваш файл будет считаться слишком большим. Как только ваше видео превысит этот лимит, чтобы загрузить его, вам нужно будет разбить его на фрагменты и отправить таким образом. Вы отправляете каждый фрагмент, и сервер собирает его для вас.

В этом руководстве мы рассмотрим простой пример загрузки большого видео.

Предпосылки

Вам потребуется доступ к Python и вам потребуется установить библиотеку запросов, если она еще не добавлена

Что вы будете делать

Это краткий обзор того, что вы собираетесь сделать, чтобы загрузить большое видео.

Вы пройдете аутентификацию в api.video с помощью своего ключа API и получите токен со сроком действия один час, который можно использовать для доступа ко всем другим конечным точкам api.video.

Устранение неполадок / На что обратить внимание

Если вы решите создать свой собственный загрузчик, вам помогут несколько вещей:

Помните, что вы должны открывать файл как двоичный файл и работать с ним как с двоичным файлом. Его легко забыть и открыть без добавления «rb» или, в зависимости от того, что вы делаете, «wb».

При использовании заголовка Content-Range необходимо убедиться, что вы указываете правильный набор отправляемых байтов. Если вы ошибетесь хотя бы на один байт, это не сработает. Вы получите странные ошибки, такие как: UnicodeDecodeError: кодек 'utf-8' не может декодировать байт 0xd1 в позиции 52: недопустимый байт продолжения. И решение часто простое исправление - исправьте, как вы перечисляете свои байты в заголовке.< /p>

Когда вы отправляете байты в заголовке Content-Range, они включаются. Если вы хотите отправить первые 100 байтов, вы записываете их как 0-99. Это может сбивать с толку, когда вы разбиваете свой файл на куски, потому что вы можете сказать «захватить первые 100 байтов», а компьютер знает, что нужно захватить 0-99. Когда вы говорите «возьмите следующие 100 байтов», компьютер возьмет 100-199. Однако легко написать динамический заголовок, где вы допускаете ошибки, например перечисляя 0–100 вместо 0–99, или начиная с одного и того же байта, например, 0–100, а затем 100–200. Все эти виды ошибок вызовут ошибку декодирования или кодирования. Если вы решите создать собственное средство загрузки вместо использования этого примера, имейте это в виду.

Если вы пометите тип отправляемого файла, это может вызвать непредвиденные проблемы. Этот пример работает, открывая, читая и отправляя видеофайл в виде фрагментов двоичных данных. Когда оно приходит, оно кодируется для вас в HLS, независимо от того, с какого видео оно начиналось.

Пример кода

Прохождение кода

Хотите узнать подробнее, как это работает? Отлично, поехали! Первые несколько разделов могут выглядеть как некоторые другие записи в блоге, прокрутите вниз, чтобы обсудить новые материалы, если это так.

Далее давайте назначим переменную для каждой конечной точки, которую мы будем использовать, с ними будет немного проще работать. Здесь мы назначим два из них, а второй используем позже для построения третьего:

Конечная точка аутентификации. Сюда мы отправляем ключ API для обмена на токен. В примере кода это auth_url.

Конечная точка видео. В частности, мы будем использовать функцию этой конечной точки для создания видео. В примере кода это create_url.

Конечная точка загрузки видео. Она очень похожа на другую конечную точку. Это create_url + "/videoId" + "/source". Мы создадим его после того, как получим идентификатор видео для работы.

Аутентификация – получите токен

Мы подготовим наши заголовки и полезные данные для аутентификации, а затем отправим запрос POST на api.video. С API api.video вы начинаете аутентификацию, отправляя запрос с использованием вашего ключа API для получения токена. Вы можете использовать свою песочницу или производственный ключ, серверная часть выяснит, что вы используете, и обработает его соответствующим образом. Если вы решите использовать свои учетные данные тестовой среды для этого пошагового руководства, ваше видео будет загружено с водяным знаком «ТОЛЬКО ДЛЯ РАЗРАБОТКИ».

Теперь нам нужно получить токен из нашего ответа, чтобы мы могли аутентифицироваться с остальными конечными точками api.video, когда мы хотим что-то сделать. Чтобы получить токен, мы преобразуем ответ в JSON, а затем извлечем токен из словаря JSON.

Настройка видеоконтейнера

Используя токен, мы подготовим заголовки и полезные данные для нашего следующего запроса, который будет заключаться в том, чтобы попросить api.video создать для нас видеоконтейнер.

Конечные точки API.video используют аутентификацию носителя. Добавьте заголовок авторизации для аутентификации носителя в свой список заголовков, а затем для полезной нагрузки мы сохраним его простым, только заголовок и описание. А как насчет пути к вашему файлу? Не волнуйтесь, мы просто создаем контейнер прямо сейчас. При загрузке с компьютера вы сначала создаете контейнер, а затем загружаете файлы.

Отправьте запрос и получите идентификатор видео

В следующей части нашего пошагового руководства мы отправим запрос, преобразуем ответ в формат JSON и получим идентификатор видео. Нам нужен videoId, чтобы мы могли сообщить api.video, в какой контейнер мы хотим загрузить наше видео.

Создайте конечную точку для загрузки вашего видео

Настройте конечную точку, на которую вы будете загружать видео, состоящую из " https://ws.api.video/videos " + "/" + videoId + "/source".

Создание средства чтения блоков данных

Чтобы разбить данные на фрагменты, вам необходимо решить, насколько большим должен быть каждый фрагмент, а затем из открытого файла продолжить захват следующего фрагмента данных для чтения. Мы установим размер блока в 1000000 байт. Это довольно мало, если вы хотите попробовать образец с меньшим видеофайлом, чтобы увидеть, как он работает. Если вы планируете начать использовать этот считыватель фрагментов данных, увеличьте размер фрагмента. Хороший размер составляет около 50–80 МБ или около 50000000–80000000 байт.

Эта функция предполагает, что вы уже открыли свой файл в другом месте и используете yield. Что это делает, так это возвращает генератор. Каждый раз, когда вы используете эту функцию как часть цикла for, она будет работать до тех пор, пока не достигнет yield, а затем вернет значение. Yield «запоминает», где вы остановились, поэтому каждый раз, когда вы выполняете цикл, он будет возвращать новый фрагмент данных.

Начните загрузку большого видео


Вот наша следующая функция. Это функция загрузки, и она содержит наш считыватель фрагментов. Что мы делаем здесь, так это используем библиотеку os для получения некоторых сведений о файле, чтобы мы знали, насколько велик файл, который мы собираемся отправить, путь к нему и имя файла.

Открываем наш файл и ВНИМАНИЕ. мы открываем наш файл в двоичном формате. Это важно помнить, поскольку открытие видеофайла в других форматах, вероятно, не сработает.

Далее мы настроим наш индекс, который будет представлять, в какой точке файла мы находимся. Мы также устанавливаем смещение, которое показывает, насколько далеко вперед нужно переместить индекс после отправки каждого фрагмента.

Затем мы начинаем читать фрагменты данных. Для каждого фрагмента данных мы готовим заголовок Content-Range, чтобы правильно указать, какую часть файла мы отправляем в байтах. Чтобы отправить наш фрагмент данных, нам нужно поместить его в словарь файла с одним элементом. Мы делаем это, а затем для удобочитаемости присваиваем его переменной. Тогда мы отправляем наш запрос! Это будет повторяться до тех пор, пока не закончатся блоки данных (последний блок, вероятно, будет меньше остальных).

Другие заголовки не нужны.

Вы узнаете об успешном завершении отправки последнего фрагмента. Можно получить ответ -200- для каждого фрагмента, а затем в самом конце это не сработает, поэтому обязательно просмотрите загрузку видео в первый раз. Успех обозначается ответом на последний фрагмент, где вы получите что-то вроде этого:

Проверьте статус своего видео на панели управления . Если у вас очень большой видеофайл, подождите несколько минут, пока api.video завершит его обработку. Когда обработка будет завершена, вы сможете увидеть эскиз своего видео и воспроизвести его на панели инструментов.

Если загрузка вашего видео не удалась, вы не получите подробное сообщение, указанное выше. Вы можете получить дополнительный ответ 200 или ответ 400 для каждого фрагмента, в зависимости от того, насколько пошло не так с вашей загрузкой. На панели инструментов вы можете увидеть, что ваше видео загружено, но оно зависает в обработке. Если это произойдет, проверьте свой код или сообщите нам о своей проблеме на форуме сообщества.

Есть ли способ отправить файл с помощью POST из скрипта Python?

9 ответов 9

Запросы упрощают загрузку файлов с кодировкой Multipart:

Вот и все. Я не шучу — это одна строка кода. Файл отправлен. Давайте проверим:

Я пытаюсь сделать то же самое, и все работает нормально, если размер файла меньше ~1,5 МБ. иначе выдает ошибку.. пожалуйста, посмотрите здесь.

что я пытаюсь сделать, так это войти на какой-то сайт, используя запрос, который я выполнил успешно, но теперь я хочу загрузить видео после входа в систему, а в форме есть разные поля, которые необходимо заполнить перед отправкой. Итак, как мне передать такие значения, как описание видео, название видео и т. д.

Этот ответ следует обновить, чтобы включить в него предложение Хьюлле об использовании диспетчера контекста для обеспечения закрытия файла.

Да. Вы должны использовать модуль urllib2 и кодировать, используя тип содержимого multipart/form-data. Вот пример кода для начала — это немного больше, чем просто загрузка файла, но вы должны прочитать его и увидеть, как он работает:

вызов run_upload (<'server':'', 'thread':''>, paths=['/path/to/file.txt']) вызывает ошибку в этой строке: upload_file (path), потому что "upload файл" требует 3 параметра, поэтому я заменяю его этой строкой upload_file (path, 1, 1)

Похоже, запросы python не обрабатывают очень большие файлы, состоящие из нескольких частей.

В документации рекомендуется изучить запросы-toolbelt .

Единственное, что мешает вам использовать urlopen непосредственно для файлового объекта, — это тот факт, что во встроенном файловом объекте отсутствует определение len. Простой способ — создать подкласс, который предоставляет urlopen правильный файл. Я также изменил заголовок Content-Type в файле ниже.

@robert Я тестирую ваш код на Python2.7, но он не работает. urlopen(Request(theUrl, theFile, . )) просто кодирует содержимое файла, как если бы это было обычное сообщение, но не может указать правильное поле формы. Я даже пробую вариант urlopen(theUrl, urlencode(<'serverside_field_name': EnhancedFile('my_file.txt')>)), он загружает файл, но (конечно!) с неправильным содержимым как . Я что-то пропустил?

Спасибо за ответ. Используя приведенный выше код, я передал необработанный файл изображения размером 2,2 ГБ с помощью запроса PUT на веб-сервер.

Библиотека плакатов Криса Этли очень хорошо подходит для этого (особенно удобная функция poster.encode.multipart_encode() ). В качестве бонуса он поддерживает потоковую передачу больших файлов без загрузки всего файла в память. См. также проблему Python 3244.

Я пытаюсь протестировать API-интерфейс django rest, и он у меня работает:

В этом руководстве мы покажем, как загрузить файл с сервера Python на другой сервер, отправив запрос POST с multipart/form-data с помощью библиотеки запросов Python.

Мы будем использовать два сервера. Сервер, который получает файл, не обязательно должен быть сервером Python, но, поскольку мы ранее создали его с помощью Django в этом руководстве, давайте использовать его вместо того, чтобы заново изобретать колесо.

Примечание. Обычно мы загружаем файлы с клиента на сервер, но в этом руководстве мы увидим, как мы можем загружать файлы с сервера на другой веб-сервер с помощью Python и библиотеки запросов.

Откройте новый терминал, создайте и активируйте виртуальную среду:

Затем клонируйте репозиторий GitHub и установите зависимости:

Затем запустите сервер, используя следующие команды:

Сервер будет доступен по адресу 127.0.0.1:8000 и предоставит конечную точку /upload, которая принимает запрос POST.

Примечание. На этом сервере также включен CORS, что означает, что он может принимать запросы от разных доменов, поэтому обязательно включите CORS, если вы используете любой другой сервер.

Создание сервера Flask

Теперь давайте приступим к созданию загружающего сервера Python, который будет использовать библиотеку запросов для отправки запросов POST на конечную точку 127.0.0.1:8000/upload для загрузки файла между двумя серверами.

Установка запросов

Давайте установим библиотеку запросов с помощью pip :

Установка Flask

Мы будем использовать Flask; единый файл и легкая веб-инфраструктура для создания сервера Python, который загружает файл. Сначала установите флягу с помощью pip :

Далее создайте файл server.py и добавьте следующий код:

Мы создаем маршрут / для рендеринга шаблона index.html, который будет отображать форму, и маршрут /handle_form, который будет обрабатывать составную форму, получать загруженный файл из массива request.files[] и возвращать его. Мы будем использовать этот метод для отправки формы на сервер django с помощью библиотеки запросов.

Далее создайте папку шаблонов и добавьте файл index.html со следующим кодом:

Мы создаем форму типа кодировки multipart/form-data, которая имеет файловое поле для выбора файла с жесткого диска.

Отправка файлов с помощью библиотеки запросов

handle_form() нашего приложения flask получает опубликованный файл, но не сохраняет его. Вместо этого мы будем использовать библиотеку запросов, чтобы загрузить ее на сервер django.

Просто измените метод handle_form() следующим образом:

Мы получаем опубликованную форму из массива request.Files, затем используем метод request.post() для загрузки файла на другой сервер с помощью запроса POST. Если запросы выполнены успешно, r.ok будет иметь значение True.

Затем запустите сервер с помощью следующей команды:

Ваш сервер Python будет доступен по адресу 127.0.0.1:8080.

Если вы выберете файл и загрузите его, он должен быть загружен в папку media на сервере django.

Заключение

В этом руководстве вы увидели, как можно использовать Python и библиотеку запросов для загрузки файла с сервера на другой сервер.

Я выполняю простую задачу по загрузке файла с помощью библиотеки запросов Python. Я искал Stack Overflow, и ни у кого не было такой же проблемы, а именно, что файл не получен сервером:

Я заполняю значение ключевого слова «upload_file» своим именем файла, потому что, если я оставлю это поле пустым, будет сказано

Появляется, только если файл пуст. Поэтому я застрял в том, как успешно отправить мой файл.Я знаю, что файл работает, потому что, если я зайду на этот веб-сайт и вручную заполню форму, он вернет хороший список совпадающих объектов, что мне и нужно. Буду очень признателен за любые подсказки.

Некоторые другие темы, связанные (но не отвечающие на мою проблему):

Если upload_file означает файл, используйте:

и запросы будут отправлять тело POST, состоящее из нескольких частей, с полем upload_file, в котором указано содержимое файла file.txt.

Имя файла будет включено в заголовок mime для определенного поля:

Обратите внимание на параметр filename="file.txt".

Вы можете использовать кортеж для значения сопоставления файлов, содержащий от 2 до 4 элементов, если вам нужно больше контроля. Первый элемент — это имя файла, за которым следует содержимое, а также необязательное значение заголовка типа содержимого и необязательное сопоставление дополнительных заголовков:

Это задает альтернативное имя файла и тип контента, исключая необязательные заголовки.

Если вы хотите, чтобы все тело POST было взято из файла (без указания других полей), не используйте параметр files, а просто отправьте файл непосредственно как данные . Затем вы также можете установить заголовок Content-Type, так как в противном случае он не будет установлен. См. Запросы Python — данные POST из файла.

(2018) новая библиотека запросов python упростила этот процесс, мы можем использовать переменную ‘files’, чтобы сигнализировать о том, что мы хотим загрузить файл с кодировкой, состоящей из нескольких частей

Загрузка клиента

Если вы хотите загрузить один файл с библиотекой запросов Python, тогда библиотека запросов поддерживает потоковую загрузку, что позволяет отправлять большие файлы или потоки без чтения в память.

На стороне сервера

Затем сохраните файл на стороне server.py, чтобы сохранить поток в файл без загрузки в память. Ниже приведен пример использования загрузки файлов Flask.

Или используйте синтаксический анализ данных формы werkzeug, как указано в исправлении проблемы «загрузки больших файлов, потребляющих память», чтобы избежать неэффективного использования памяти при загрузке больших файлов (файл размером 22 ГиБ за ~60 секунд). постоянный размер около 13 МБ).

Ответ @martijn-pieters правильный, однако я хотел добавить немного контекста к data=, а также к другой стороне, на сервере Flask, в случае, когда вы пытаетесь загрузить файлы и< /em> JSON.

Со стороны запроса это работает так, как описывает Мартин:

Однако на стороне Flask (принимающий веб-сервер на другой стороне этого POST) мне пришлось использовать форму

body = request.get_json() ничего не вернет. body = request.get_data() вернет большой двоичный объект, содержащий множество вещей, таких как имя файла и т. д.

Плохая часть: на стороне клиента изменение data=<> на json=<> приводит к тому, что этот сервер не может читать пары KV! Например, это приведет к <> body выше:

Это плохо, потому что сервер не контролирует, как пользователь форматирует запрос; и json= станет привычкой запросов пользователей.

В Ubuntu вы можете применить этот способ,

сохранить файл в каком-либо месте (временно), а затем открыть и отправить его в API

Если вы не получили ответ на свой вопрос, прочитайте всю ветку или оставьте комментарий ниже, и мы ответим на ваш вопрос!

Читайте также: