Отправка файла и передача параметра с помощью pycurl
Я уже разобрался как это сделать вам, добавляет, удаляет и через pycurl из.
Тем не менее, я не могу понять, что является эквивалентом этой командной строки curl (которая отлично работает) для python:
curl -u admin:geoserver -XPOST -H 'Content-type: application/vnd.ogc.sld+xml'
-d @/Users/rburhum/src/calthorpe/calthorpe/server/calthorpe/media/styles/1_my-scenario
"http://127.0.0.1:8080/geoserver/rest/styles?name=1_my-scenario" -v
Я видел образцы в репо . Тем не менее, передача одного параметра (в данном случае name) и загружаемого файла, похоже, не работает.
Для вызовов PUT я успешно использовал:
filesize = path.getsize(sldFile)
f = open(sldFile,'rb')
c = pycurl.Curl()
c.setopt(pycurl.HTTPHEADER, ["Content-type: application/vnd.ogc.sld+xml"])
c.setopt(pycurl.USERPWD, GEOSERVER_USER + ':' + GEOSERVER_PASSWORD)
c.setopt(pycurl.INFILESIZE, filesize)
c.setopt(c.URL, str(GEOSERVER_URL + '/rest/styles/' + path.basename(sldFile)))
c.setopt(pycurl.PUT, 1)
c.setopt(pycurl.INFILE, f)
c.perform()
f.close()
Таким образом, я наивно полагал, что эквивалентом поста будет:
filesize = path.getsize(sldFile)
f = open(sldFile,'rb')
c = pycurl.Curl()
c.setopt(c.URL, str(GEOSERVER_URL + '/rest/styles?name=' + path.basename(sldFile)))
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.HTTPHEADER, ["Content-type: application/vnd.ogc.sld+xml"])
c.setopt(pycurl.USERPWD, GEOSERVER_USER + ':' + GEOSERVER_PASSWORD)
c.setopt(pycurl.INFILESIZE, filesize)
c.setopt(pycurl.INFILE, f)
c.perform()
f.close()
Подробный вывод команды curl показывает следующее:
(calthorpe_env) rburhum@peru.local ~ / src / calthorpe / calthorpe / сервер / calthorpe $calthorpe / server / calthorpe POST-H ' Content-type: application/vnd.ОГК.СЛД на+XML' -д@/пользователи/rburhum/ГРЦ/калторп/калторп/сервер/калторп/СМИ/стили/1_my-сценарий "http://127.0.0.1:8080/geoserver/rest/styles?name=1_my-scenary" - v * О подключении() к порту 127.0.0.1 8080 (#0) * Попытка 127.0.0.1... связанный * Подключен к порту 127.0.0.1 (127.0.0.1) 8080 (#0) * Авторизация сервера с использованием Basic с пользователем 'admin'
POST / geoserver/rest / styles?name=1_my-сценарий HTTP / 1.1 Авторизация: Базовая YWRtaW46Z2Vvc2VydmVy Пользователь-агент: скручиваемость/7.21.4 (универсальный-яблоко-darwin11.0) libcurl о/7.21.4 OpenSSL / 0.9.8 r zlib / 1.2.5 Хост: 127.0.0.1: 8080 Принять: / Тип контента: application/vnd.ОГК.СЛД+XML-файле Содержание-Длина: 28135 Ожидать: 100-ПРОДОЛЖИТЬ
> http://127.0.0.1:8080/geoserver/rest/styles/1_my-scenario
Я ясно вижу, что длина контента правильная.
В напротив, когда я делаю подробный вывод моего почтового кода выше, я вижу, что длина содержимого равна -1 (и, следовательно, файл не передается, и сервер возвращает 500). Я издевался над переменной HTTPPOST, которая при определенных комбинациях делает длину содержимого правильной, но я все еще не могу получить точный эквивалент команды CURL выше для работы.
1 ответ:
Мне пришлось объединить несколько примеров, чтобы найти правильную комбинацию, и, конечно, я использовал некоторую помощь от некоторых хороших людей на IRC-канале. Единственный способ заставить его работать - это сделать небольшую вариацию этого образцаpycurl , который не работал, как описано для меня.
class FileReader: def __init__(self, fp): self.fp = fp def read_callback(self, size): return self.fp.read(size)
Затем позже я бы настроил вызов следующим образом:
c = pycurl.Curl() c.setopt(c.URL, str(GEOSERVER_URL + '/rest/styles?name=' + path.basename(sldFile))) c.setopt(pycurl.POST, 1) filesize = path.getsize(sldFile) f = open(sldFile,'rb') c.setopt(pycurl.POSTFIELDSIZE, filesize) c.setopt(pycurl.READFUNCTION, FileReader(f).read_callback) c.setopt(pycurl.HTTPHEADER, ["Content-type: application/vnd.ogc.sld+xml"]) c.setopt(pycurl.USERPWD, GEOSERVER_USER + ':' + GEOSERVER_PASSWORD) c.perform() f.close()
Обратите внимание, что исходный образец не использовал POSTFIELDSIZE (только имел INFILESIZE), без него я не мог получить его работа.
В качестве примечания, в моем случае sldFile уже был slugified, так что не нужно urlencode, в противном случае, вы можете сделать это.