it-swarm.com.ru

Http POST в Java (с загрузкой файлов)

Что я хочу сделать, это отправить веб-форму из приложения Java. Форма, которую мне нужно заполнить, находится здесь: http://cando-dna-origami.org/

Когда форма отправлена, сервер отправляет электронное письмо с подтверждением на указанный адрес электронной почты, который на данный момент я просто проверяю вручную. Я попытался заполнить форму вручную, и письма отправляются нормально. (Следует также отметить, что при неправильном заполнении формы страница просто обновляется и не дает никаких отзывов).

Я никогда ничего не делал с http раньше, но некоторое время я оглядывался по сторонам и придумал следующий код, который должен отправить запрос POST на сервер:

    String data = "name=M+V&affiliation=Company&email="
            + URLEncoder.encode("[email protected]", "UTF-8")
            + "&axialRise=0.34&helixDiameter=2.25&axialStiffness=1100&bendingStiffness=230" +
            "&torsionalStiffness=460&nickStiffness=0.01&resolution=course&jsonUpload="
            + URLEncoder.encode("C:/Users/Marjie/Downloads/twisted_DNA_bundles/monotwist.L1.v1.json",
            "UTF-8") + "&type=square";

    URL page = new URL("http://cando-dna-origami.org/");
    HttpURLConnection con = (HttpURLConnection) page.openConnection();

    con.setDoOutput(true);
    con.setRequestMethod("POST");
    con.connect();

    OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream());
    out.write(data);
    out.flush();

    System.out.println(con.getResponseCode());
    System.out.println(con.getResponseMessage());

    out.close();
    con.disconnect();

Однако, когда он запускается, он, похоже, ничего не делает - то есть я не получаю никаких писем, хотя программа выводит «200 OK» на System.out, что, кажется, указывает на то, что что-то получено с сервера , хотя я не уверен, что именно это означает. Я думаю, что проблема может заключаться в загрузке файла, так как я не был уверен, что этот тип данных требует другого формата.

Это правильный способ отправки запроса POST с использованием Java? Нужно ли делать что-то другое для загрузки файла? Спасибо!


Прочитав пост Адама, я использовал Apache HttpClient и написал следующий код:

    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("type", "square"));
    //... add more parameters

    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);

    HttpPost post = new HttpPost("http://cando-dna-origami.org/");
    post.setEntity(entity);

    HttpResponse response = new DefaultHttpClient().execute(post);
    post = new HttpPost("http://cando-dna-origami.org/");

    post.setEntity(new FileEntity(new File("C:/Users/Marjie/Downloads/twisted_DNA_bundles/monotwist.L1.v1.json"), "text/plain; charset=\"UTF-8\""));
    HttpResponse responseTwo = new DefaultHttpClient().execute(post);

Однако, это все еще, кажется, не работает; опять же, я не был уверен, как загруженный файл вписывается в форму, поэтому я попытался просто отправить два отдельных запроса POST, один с формой и один с другими данными. Я все еще ищу способ объединить их в один запрос; Кто-нибудь знает что-нибудь об этом?

15
Reyan

Возможно, вам лучше использовать что-то вроде Apache HttpClient , с помощью которого вы можете программно создать запрос POST.

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://.../whatever");

List <NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("param1", "value1"));
params.add(new BasicNameValuePair("param2", "value2"));
...

httpost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));

HttpResponse response = httpclient.execute(httppost);

Если вам нужно загрузить файл вместе с формой, вам нужно будет использовать вместо него MultipartEntity:

MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("someParam", "someValue");
reqEntity.addPart("someFile", new FileBody("/some/file"));
....

httpost.setEntity(reqEntity);

Есть несколько примеров программ на их сайте . «Вход в систему на основе форм» и «Объект запроса, состоящий из нескольких частей» являются хорошими примерами для начала.

Может также стоить проверить ваши соединения и взглянуть на базовые данные сети, чтобы увидеть, что происходит. Что-то вроде Firebug позволит вам точно видеть, что происходит в вашем браузере, и вы можете включить ведение журнала HttpClient, чтобы увидеть все данные, которыми обмениваются в вашей программе. Кроме того, вы можете использовать что-то вроде Wireshark или Fiddler для наблюдения за вашим сетевым трафиком в режиме реального времени. Это может дать вам лучшее представление о том, что именно делает ваш браузер, по сравнению с тем, что делает ваша программа.

17
Adam Batkin

Вы должны окончательно использовать apaches HTTPClient для этой работы! Это делает жизнь намного проще. Вот пример, как загрузить файл с помощью Apache HttpClient. 

byte[] data = outStream.toByteArray()
HttpClient client = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://localhost:8080/YourResource");

ByteArrayBody byteArrayBody = new ByteArrayBody(data, "application/json", "some.json");
MultipartEntity multipartEntity = new MultipartEntity();
multipartEntity.addPart("upload", byteArrayBody);
httpPost.setEntity( multipartEntity );

HttpResponse response = client.execute(httpPost);
Reader reader = new InputStreamReader(response.getEntity().getContent());

Дайте мне знать, если у вас есть дополнительные вопросы. 

2
Robert Reiz

В настоящее время я пишу небольшой веб-сервер и проверил ваш клиентский запрос. Мой сервер получает следующий запрос:

User-Agent: Java/1.6.0_20 
Host: localhost:1700 
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 
Connection: keep-alive 
Content-type: application/x-www-form-urlencoded 
Content-Length: 287 
name=M+V&affiliation=Company&email=m.v%40gmail.com&axialRise=0.34&helixDiameter=2.25&axialStiffness=1100&bendingStiffness=230&torsionalStiffness=460&nickStiffness=0.01&resolution=course&jsonUpload=C%3A%2FUsers%2FMarjie%2FDownloads%2Ftwisted_DNA_bundles%2Fmonotwist.L1.v1.json&type=square

Вам следует проверить формат отправляемых данных POST, скорее всего, они не обрабатываются сервером так, как вы ожидаете.

1
Alex

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

Этот POST запрос имеет тип multipart, чтобы разрешить отправку/загрузку файла на сервер. 

Многокомпонентный запрос состоит из основного заголовка и строки разделителя с именем border, чтобы отличить каждую часть от другой (этот разделитель будет идти в потоке со строкой "-" (две черты) перед ней, и каждая часть имеет свой собственный маленький заголовок, чтобы сообщить его тип и еще несколько метаданных.

Моя задача состояла в том, чтобы создать файл PDF с использованием некоторых онлайн-сервисов, но все составные примеры POST просто не помогли ...

Мне нужно было упаковать документ HTML вместе с его изображениями, файлами JS и CSS в файл Zip/TAR, загрузить его в онлайн-сервис преобразования html2pdf и получить результат в виде PDF документа обратно в ответ ( поток) из службы.

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

Вызов method (для этой службы) выглядит примерно так: [class instance name].sendPOSTRequest("http://htmlpdfapi.com/api/v1/pdf", "Token 6hr4-AmqZDrFVjAcJGykjYyXfwG1wER4", "/home/user/project/srv/files/example.Zip", "result.pdf");

Вот мой код, который был проверен и работает на 100%:

public void sendPOSTRequest(String url, String authData, String attachmentFilePath, String outputFilePathName)
{
    String charset = "UTF-8";
    File binaryFile = new File(attachmentFilePath);
    String boundary = "------------------------" + Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
    String CRLF = "\r\n"; // Line separator required by multipart/form-data.
    int    responseCode = 0;

    try 
    {
        //Set POST general headers along with the boundary string (the seperator string of each part)
        URLConnection connection = new URL(url).openConnection();
        connection.setDoOutput(true);
        connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
        connection.addRequestProperty("User-Agent", "CheckpaySrv/1.0.0");
        connection.addRequestProperty("Accept", "*/*");
        connection.addRequestProperty("Authentication", authData);

        OutputStream output = connection.getOutputStream();
        PrintWriter writer  = new PrintWriter(new OutputStreamWriter(output, charset), true);

        // Send binary file - part
        // Part header
        writer.append("--" + boundary).append(CRLF);
        writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
        writer.append("Content-Type: application/octet-stream").append(CRLF);// + URLConnection.guessContentTypeFromName(binaryFile.getName())).append(CRLF);
        writer.append(CRLF).flush();

        // File data
        Files.copy(binaryFile.toPath(), output);
        output.flush(); 

        // End of multipart/form-data.
        writer.append(CRLF).append("--" + boundary + "--").flush();

        responseCode = ((HttpURLConnection) connection).getResponseCode();


        if(responseCode !=200) //We operate only on HTTP code 200
            return;

        InputStream Instream = ((HttpURLConnection) connection).getInputStream();

        // Write PDF file 
        BufferedInputStream BISin = new BufferedInputStream(Instream);
        FileOutputStream FOSfile  = new FileOutputStream(outputFilePathName);
        BufferedOutputStream out  = new BufferedOutputStream(FOSfile);

        int i;
        while ((i = BISin.read()) != -1) {
            out.write(i);
        }

        // Cleanup
        out.flush();
        out.close();


    }
    catch(Exception e)
    {
        e.printStackTrace();
    }

}
1
JamesC

Вот пример, который я получил, который использует Apache httpclient. Также не забудьте добавить эти зависимости:

    <dependency>
        <groupId>org.Apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.4.1</version>
    </dependency>


    <dependency>
        <groupId>org.Apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.4.1</version>
    </dependency>

Код: HttpClient httpclient = HttpClientBuilder.create (). Build (); 

HttpPost httppost = new HttpPost(DataSources.TORRENT_UPLOAD_URL);

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.addPart("a_field_name", new FileBody(torrentFile));

HttpEntity entity = builder.build();

httppost.setEntity(entity);

HttpResponse response = httpclient.execute(httppost);
0
thouliha