Как я могу отправить файл в запросе POST? - PullRequest
5 голосов
/ 02 октября 2009

Я создаю API-интерфейс clojure для своего веб-сайта, который по сути является оболочкой для исходного веб-API. Одна из функций, которую я не могу реализовать, - это отправка файлов через POST-запросы, в основном то, что я делал бы в оболочке с curl -F foo=bar baz=@bak.jpg foobar.com.

Я использую clojure-http-client и первоначально пробовал форму (resourcefully/post "foobar.com" {} {:foo "bar" :baz (File. "bak.jpg")}), но поле: baz было проигнорировано получающим скриптом, как если бы я отправил только: foo. Позже я попытался изменить File. на FileInputStream, так как [строка 51] [2] client.clj, кажется, проверяет этот конкретный класс, но все же получил те же результаты.

Затем я создал страницу php, которая просто печатает $ _POST, чтобы проверить мой запрос, и, очевидно, данные объектов отправляются буквально. Взгляните:

Clojure => (изобретательно / post "http://ptchan.org/pttest.php" {} {: foo" bar ": baz" /tmp/bak.jpg "}) {: body-seq ("Array" "(" "[foo] => bar" "[baz] => /tmp/bak.jpg" ")"),: код 200,: msg "ОК",: метод «POST»,: headers {: date («Пт, 02 октября 2009 11:41:15 GMT»),: var («Accept-Encoding»),: content-length («53»),: connection («close "),: content-type (" text / html "),: server (" Apache / 2.2.9 (Debian) PHP / 5.2.6-1 + lenny3 с Suhosin-Patch "),: x-powered-by ( "PHP / 5.2.6-1 + lenny3")},: get-header #,: cookie nil,: url "http://ptchan.org/pttest.php"}

Clojure => (находчиво / post "http://ptchan.org/pttest.php" {} {: foo" bar ": baz (File." /Tmp/bak.jpg ")}) {: body-seq ("Array" "(" "[foo] => bar" "[baz] => /tmp/bak.jpg" ")"),: код 200,: msg "ОК",: метод «POST»,: headers {: date («Пт, 02 октября 2009 11:41:30 GMT»),: var («Accept-Encoding»),: content-length («53»),: connection («close "),: content-type (" text / html "),: server (" Apache / 2.2.9 (Debian) PHP / 5.2.6-1 + lenny3 с Suhosin-Patch "),: x-powered-by ( "PHP / 5.2.6-1 + lenny3")},: get-header #,: cookie nil,: url "http://ptchan.org/pttest.php"}

Clojure => (изобретательно / post "http://ptchan.org/pttest.php" {} {: foo" bar ": baz (FileInputStream." /Tmp/bak.jpg ")}) {: body-seq ("Array" "(" "[foo] => bar" "[baz] => java.io.FileInputStream@320f6398" ")"),: код 200,: сообщение "ОК",: method "POST",: headers {: date ("Пт, 02 октября 2009 11:41:47 GMT"),: var ("Accept-Encoding"),: content-length ("73"),: connection (" close "),: content-type (" text / html "),: server (" Apache / 2.2.9 (Debian) PHP / 5.2.6-1 + lenny3 с Suhosin-Patch "),: x-powered-by ("PHP / 5.2.6-1 + lenny3")},: get-header #,: cookie nil,: url "http://ptchan.org/pttest.php"}

Я не совсем уверен, как поступить. Любое предложение? Общие советы по отладке также приветствуются!

Спасибо

Ответы [ 2 ]

4 голосов
/ 03 октября 2009

Попробуйте использовать clojure-apache-http , оболочку Clojure для полнофункциональных библиотек Apache HTTP. Он поддерживает multipart / form-data POST.

3 голосов
/ 03 октября 2009

Я не уверен, что это возможно с помощью clojure-http-client. Насколько я вижу в исходном коде , если вы передадите карту в качестве аргумента body, она будет URL кодировать каждый элемент и отправлять его. Похоже, что вы можете только POST файлы как целые тела, без каких-либо других аргументов. Итак, поддержка multipart.

(let [out (.getOutputStream connection)]
(cond
  (string? body) (spit out body)
  (map? body) (spit out (url-encode body))
  (instance? InputStream body)
  (let [bytes (make-array Byte/TYPE 1000)]
    (loop [#^InputStream stream body
           bytes-read (.read stream bytes)]
      (when (pos? bytes-read)
        (.write out bytes 0 bytes-read)
        (recur stream (.read stream bytes))))))
(.close out)))
...