Как открыть файл и использовать request.put для правильной загрузки файла в Python?

Я пытаюсь использовать библиотеку запросов в Python для загрузки файла в хранилище общих ресурсов Fedora на локальном хосте. Я вполне уверен, что моя главная проблема не в понимании open() / read() и что мне нужно сделать, чтобы отправить данные с HTTP-запросом.

def postBinary(fileName,dirPath,url):
    path = dirPath+'/'+fileName
    print('to ' + url + '\n' + path)
    openBin = {'file':(fileName,open(path,'rb').read())}
    headers = {'Slug': fileName} #not important
    r = requests.put(url, files=openBin,headers=headers, auth=HTTPBasicAuth('username', 'pass'))
    print(r.text)
    print("and the url used:")
    print(r.url)

Это успешно загрузит файл в хранилище, но он будет немного больше и поврежден после. Например, изображение размером 6,6 КБ стало 6,75 КБ и больше не могло быть открыто.

Так как же мне правильно открыть и загрузить файл, используя put в python?

Дополнительные детали:

  • когда я заменю files=openBin с data=openBin Я заканчиваю со своим словарем, и я предполагаю данные как строку. Я не знаю, полезна ли эта информация или нет. "file=FILE_NAME.extension&file=TYPE89a%24%02Q%03%E7%FF%00E%5B%19%FC%.... и размер файла увеличивается до количества мегабайт
  • Я специально использую put, потому что конечная точка RESTful HTTP API fedora говорит, что нужно использовать put. Следующая команда работает.

    curl -u username:password -H "Content-Type: text/plain" -X PUT -T /path/to/someFile.jpeg http://localhost:8080/fcrepo/rest/someFile.jpeg

1 ответ

Решение

обновленный

С помощью requests.put() с files Параметр отправляет запрос в формате multipart/form-data, который, по-видимому, сервер не может обработать без повреждения данных, даже если объявлен правильный тип содержимого.

curl Команда просто выполняет PUT с необработанными данными, содержащимися в теле запроса. Вы можете создать аналогичный запрос, передав данные файла в data параметр. Укажите тип содержимого в заголовке:

headers = headers = {'Content-type': 'image/jpeg', 'Slug': fileName}
r = requests.put(url, data=open(path, 'rb'), headers=headers, auth=('username', 'pass'))

Вы можете варьировать Content-type заголовок, чтобы соответствовать полезной нагрузке при необходимости.


Попробуйте установить Content-type для файла.

Если вы уверены, что это текстовый файл, попробуйте text/plain который вы использовали в своем curl команда - даже если вы, казалось бы, загружать файл JPEG? Однако для изображения в формате JPEG используйте image/jpeg,

В противном случае для произвольных двоичных данных вы можете использовать application/octet-stream:

openBin = {'file': (fileName, open(path,'rb'), 'image/jpeg' )}

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

Другие вопросы по тегам