как создать и опубликовать составной / смешанный HTTP-запрос с помощью Apache HttpComponentst?

Я использую Apache HttpComponents v4.3.3 (maven httpclient и httpmime). Мне нужно загрузить файл с некоторыми метаданными. Команда curl, которая работает, выглядит следующим образом.

curl -k -i -H "Content-Type: multipart / mixed" -X POST --form 'field1 = val1' --form 'field2 = val2' --form '[email protected]; type = application / zip 'https://www.some.domain/

Я попытался имитировать этот пост с завитками следующим образом.

HttpEntity entity = MultiPartEntityBuilder
 .create()
 .addPart("field1",new StringBody("val1",ContentType.TEXT_PLAIN))
 .addPart("field2",new StringBody("val2",ContentType.TEXT_PLAIN))
 .addPart("file", new FileBody(new File("somefile.zip"), ContentType.create("application/zip"))
 .build();
HttpPost post = new HttpPost("https://www.some.domain");
post.addHeader("Content-Type", "multipart/mixed");

Однако после того, как я использую HttpClient для выполнения HttpPost, я получаю следующее исключение (код сервера также является Java, работающим на Jetty).

org.apache.commons.fileupload.FileUploadException: запрос был отклонен, потому что не было найдено многочастной границы

Когда я добавляю след на завиток

curl --trace - -k -i -H "Content-Type: multipart / mixed" -X POST --form 'field1 = val1' --form 'field2 = val2' --form '[email protected]; type = application / zip 'https://www.some.domain/

Я вижу, что пары поле / значение формы заданы как заголовки HTTP.

Content-Disposition: форма-данные; имя = поле1 ... значение1

Есть идеи, что я здесь делаю не так? Любая помощь приветствуется.


person Jane Wayne    schedule 22.04.2014    source источник


Ответы (2)


Я немного повозился и сделал две вещи, чтобы код заработал.

  • больше не использовать addPart (...)
  • больше не устанавливают заголовок Content-Type

Вот исправленный фрагмент, который работает, если кому-то интересно.

HttpEntity entity = MultipartEntityBuilder
 .create()
 .addTextBody("field1","val1")
 .addTextBody("field2","val2")
 .addBinaryBody("file", new File("somefile.zip"),ContentType.create("application/zip"),"somefile.zip")
 .build();
HttpPost post = new HttpPost("https://www.some.domain");
post.setEntity(entity);

Я также установил HttpComponents в режим отладки.

-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
-Dorg.apache.commons.logging.simplelog.showdatetime=true
-Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG

Оказывается, у каждой части теперь есть граница. Еще лучше, Content-Type и граница генерируются автоматически.

Тип содержимого: multipart / form-data; border = 5ejxpaJqXwk2n_3IVZagQ1U0_J_X9MdGvst9n2Tc

person Jane Wayne    schedule 22.04.2014
comment
Не знаю, почему вы не получили голосов - это ИДЕАЛЬНОЕ решение для multipart на Android! Другие вещи, которые я нашел, делали все вручную, что довольно громоздко .... - person Lonzak; 23.10.2014
comment
Но это не составное / смешанное. Кажется, есть сотни ответов, как это сделать с multipart / form-data. - person unwichtich; 02.09.2016

Вот мой полный код, основанный на последнем ответе, но он немного отличается, у меня была такая же ошибка, но теперь работает (спасибо, Джейн!):

public String sendMyFile(String p_file, String p_dni, String p_born_date) throws Exception {

    HttpClient httpclient = HttpClientBuilder.create().build();

    HttpPost    httppost = new HttpPost("http://localhost:2389/TESTME_WITH_NETCAT");

    /* Campos del formulario del POST que queremos hacer */
    File        fileIN  = new File(p_file);

    /* Construimos la llamada */
    MultipartEntityBuilder reqEntity = MultipartEntityBuilder.create();

    reqEntity
            .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
            .addBinaryBody  ("p_file"               , fileIN)
            .addTextBody    ("p_dni"                , p_dni)
            .addTextBody    ("p_born_date"  , p_born_date);

    httppost.setEntity(reqEntity.build());

    System.out.println("executing request " + httppost.getRequestLine());

    HttpResponse response = httpclient.execute(httppost);

    System.out.println("1 ----------------------------------------");
    System.out.println(response.getStatusLine());
    System.out.println("2 ----------------------------------------");
    System.out.println(EntityUtils.toString(response.getEntity()));
    System.out.println("3 ----------------------------------------");

    HttpEntity resEntity = response.getEntity();

    if (resEntity != null) {
        System.out.println("Response content length: " + resEntity.getContentLength());
    }

    return "OK";
}
person nugbe    schedule 11.11.2014
comment
Добро пожаловать в Stack Overflow! Хотя этот фрагмент кода может решить вопрос, включение объяснения действительно помогает улучшить качество вашего поста. Помните, что вы отвечаете на вопросы читателей в будущем, и эти люди могут не знать причины вашего предложения кода. - person gunr2171; 16.11.2014