Java中的Http POST(带文件上传)

时间:2012-03-13 21:05:56

标签: java forms http post

我想要做的是从Java应用程序提交Web表单。我需要填写的表单位于:http://cando-dna-origami.org/

提交表单后,服务器会向给出的电子邮件地址发送一封确认电子邮件,目前我只是手工检查。我已经尝试手动填写表单,电子邮件也很好。 (还应该注意的是,当表单填写不正确时,页面只会刷新并且不会给出任何反馈。)

我之前从未做过任何关于http的事情,但我环顾了一会儿,并提出了以下代码,它应该向服务器发送一个POST请求:

    String data = "name=M+V&affiliation=Company&email="
            + URLEncoder.encode("m.v@gmail.com", "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();

然而,当它运行时它似乎没有做任何事情 - 也就是说,我没有收到任何电子邮件,虽然该程序确实向System.out打印“200 OK”,这似乎表明收到了一些东西从服务器,虽然我不确定它究竟是什么意思。我认为问题可能出在文件上传中,因为我不确定该数据类型是否需要不同的格式。

这是使用Java发送POST请求的正确方法吗?我是否需要为文件上传执行不同的操作?谢谢!


在阅读Adam的帖子后,我使用了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请求,一个与表单,一个与其他数据。我仍然在寻找一种方法将这些组合成一个请求;有人知道这个吗?

5 个答案:

答案 0 :(得分:17)

使用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);

their site上有一些示例程序。 “基于表单的登录”和“多部分编码的请求实体”是很好的例子。

测试您的连接并查看底层网络数据以查看发生的情况也是值得的。类似Firebug之类的内容可以让您准确了解浏览器中发生的情况,并且可以打开HttpClient日志记录以查看程序中交换的所有数据。或者,您可以使用Wireshark或Fiddler等实时监控网络流量。这可以让您更好地了解浏览器正在做什么,而不是您的程序正在做什么。

答案 1 :(得分:2)

你应该明确地使用apache 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 :(得分:1)

我目前正在编写一个小型Web服务器,我测试了您的请求客户端。我的服务器收到以下请求:

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数据的格式,很可能它不会像您期望的那样由服务器处理。

答案 3 :(得分:1)

由于大多数建议的Java HTTP POST请求代码无法运行,我决定向您提供完全可操作的代码,我确信您会发现有助于创建任何基于Java的POST请求在将来。

此POST请求为multipart类型,允许将文件发送/上传到服务器。

多部分请求包含一个主标题和一个名为边界的分隔符字符串,用于告诉每个部分与另一个部分(此分隔符将出现在&#34流中: - &#34;(两个破折号)前面的字符串,每个部分都有自己的小标题来告诉它的类型和一些更多的元数据。

我的任务是使用一些在线服务创建PDF文件,但所有多部分POST示例都没有做到这一点......

我需要将一个HTML文档及其图片,JS和CSS文件打包到ZIP / TAR文件中,将其上传到在线html2pdf转换服务并将结果作为PDF文档作为响应返回给我(流)来自服务。

我已检查使用以下代码的当前服务是:Htmlpdfapi.com但我确信通过微小调整,您可以将其与任何其他服务一起使用。< / p>

方法调用(对于该服务)看起来像: [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();
    }

}

答案 4 :(得分:0)

这是我使用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);