Java 中的 Http POST(带文件上传)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9692166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Http POST in Java (with file upload)
提问by Reyan
What I want to do is submit a web form from a java application. The form I need to fill out is located here: http://cando-dna-origami.org/
我想要做的是从 Java 应用程序提交 Web 表单。我需要填写的表格在这里:http: //cando-dna-origami.org/
When the form is submitted, the server sends a confirmation email to the email address given, which for now I'm just checking by hand. I've tried filling out the form manually, and the emails get sent fine. (It should also be noted that when the form is filled out incorrectly, the page just refreshes and doesn't give any feedback).
提交表单后,服务器会向给定的电子邮件地址发送一封确认电子邮件,目前我只是手动检查。我试过手动填写表格,邮件发送正常。(还需要注意的是,当表单填写不正确时,页面只会刷新,不会给出任何反馈)。
I've never done anything with http before, but I looked around for a while, and came up with the following code, which is supposed to send a POST request to the server:
我以前从未对 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();
However, when it runs it doesn't appear to do anything - that is, I don't get any emails, although the program does print "200 OK" to System.out, which seems to indicate that something got received from the server, although I'm not sure what it means exactly. I think the problem might be in the file uploading, since I wasn't sure whether that data type required a different format.
然而,当它运行时它似乎没有做任何事情——也就是说,我没有收到任何电子邮件,尽管程序确实向 System.out 打印了“200 OK”,这似乎表明从服务器收到了一些东西,虽然我不确定它的确切含义。我认为问题可能出在文件上传上,因为我不确定该数据类型是否需要不同的格式。
Is this a correct way to send a POST request using Java? Do I need to do something different for the file uploading? Thanks!
这是使用 Java 发送 POST 请求的正确方法吗?我需要为文件上传做一些不同的事情吗?谢谢!
After reading Adam's post, I used Apache HttpClient and wrote the following code:
看了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);
However, it still doesn't seem to be working; again, I wasn't sure how the uploaded file fit into the form, so I tried just sending two separate POST requests, one with the form and one with the other data. I am still looking for a way to combine these into one request; does anybody know something about this?
但是,它似乎仍然不起作用;再次,我不确定上传的文件如何适合表单,所以我尝试只发送两个单独的 POST 请求,一个是表单,一个是其他数据。我仍在寻找一种将这些组合成一个请求的方法;有人对此有所了解吗?
回答by Adam Batkin
You would probably be better off using something like Apache HttpClient, with which you can build up a POST
request programatically.
使用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);
If you need to upload a file along with your form, you will need to use a MultipartEntity
instead:
如果您需要随表单一起上传文件,则需要使用 aMultipartEntity
代替:
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("someParam", "someValue");
reqEntity.addPart("someFile", new FileBody("/some/file"));
....
httpost.setEntity(reqEntity);
There are some sample programs over on their site. The "Form based logon" and "Multipart encoded request entity" are good examples to start from.
他们的网站上有一些示例程序。“基于表单的登录”和“多部分编码的请求实体”是很好的例子。
It may also be worthwhile testing out your connections and taking a look at the underlying network data to see what is happening. Something like Firebugwill let you see exactly what is happening in your browser, and you can turn up the HttpClient logging to see all of the data exchanged in your program. Alternatively, you can use something like Wireshark or Fiddler to watch your network traffic in real-time. This may give you a better idea of exactly what your browser is doing, versus what your program is doing.
测试您的连接并查看底层网络数据以了解发生了什么也可能是值得的。Firebug 之类的东西可以让您确切地看到浏览器中发生的事情,并且您可以打开 HttpClient 日志记录以查看程序中交换的所有数据。或者,您可以使用 Wireshark 或 Fiddler 之类的工具来实时查看您的网络流量。这可能会让您更好地了解浏览器正在做什么,而不是您的程序正在做什么。
回答by Alex
I am currently writing a small web server, and I tested your request client. My server is receiving the following request:
我目前正在编写一个小型 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
You should check the format of the POST data you are sending, most probably it is not processed by the server as you would expect.
您应该检查您发送的 POST 数据的格式,很可能它没有像您期望的那样由服务器处理。
回答by Robert Reiz
You should definitively use apaches HTTPClientfor that job! It makes life much easier. Here is an example how to upload a file with apaches HttpClient.
您应该明确地使用 apaches HTTPClient来完成这项工作!它让生活变得更轻松。这是一个如何使用 apaches 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());
Let me know if you have further questions.
如果您还有其他问题,请告诉我。
回答by thouliha
Here's an example I got working that uses apache httpclient. Also, don't forget to add these dependencies:
这是我使用 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>
The code:
编码:
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);
回答by JamesC
As most of the suggested Java HTTP POST request code out there is not operational, I decided to give you my fully operational code that I'm sure you'll find helpful to create any Java-based POST request in the future.
由于大多数建议的 Java HTTP POST 请求代码都无法运行,因此我决定向您提供我完全可运行的代码,我相信您会发现这些代码在将来创建任何基于 Java 的 POST 请求时会有所帮助。
This POST request is of multipart
type to allow sending/uploading a file to the server.
此 POST 请求的multipart
类型允许向服务器发送/上传文件。
Multipart request consist of a main header and a separator string called boundaryto tell each part from the other (this separator will come in the stream with "--" (two dashes) string before it, and each part has its own small header to tell its type and some more meta-data.
多部分请求由一个主标头和一个称为边界的分隔符字符串组成,以区分每个部分(此分隔符将在流中以“--”(两个破折号)字符串的形式出现,每个部分都有自己的小标头以告诉它的类型和一些更多的元数据。
My task was to create a PDF file using some online services but all the multipart POST examples just didn't do the trick...
我的任务是使用一些在线服务创建一个 PDF 文件,但所有的多部分 POST 示例都没有成功......
I needed to pack an HTML document along with its pics, JS and CSS files in a ZIP/TAR file, upload it to an online html2pdf conversion service and get the result as a PDF document back to me as the response (stream) from the service.
我需要将 HTML 文档及其图片、JS 和 CSS 文件打包到 ZIP/TAR 文件中,将其上传到在线 html2pdf 转换服务,并将结果作为 PDF 文档返回给我,作为来自服务。
The current service I've checked the using following code is: Htmlpdfapi.combut I'm sure that with minor adjustments you'll be able to use it with any other service.
我使用以下代码检查过的当前服务是:Htmlpdfapi.com但我相信只要稍作调整,您就可以将它与任何其他服务一起使用。
The method call(for that service) looks something like:
[class instance name].sendPOSTRequest("http://htmlpdfapi.com/api/v1/pdf", "Token 6hr4-AmqZDrFVjAcJGykjYyXfwG1wER4", "/home/user/project/srv/files/example.zip", "result.pdf");
该方法调用(该服务)看起来像:
[class instance name].sendPOSTRequest("http://htmlpdfapi.com/api/v1/pdf", "Token 6hr4-AmqZDrFVjAcJGykjYyXfwG1wER4", "/home/user/project/srv/files/example.zip", "result.pdf");
Here is my code that was checked and 100% works:
这是我经过检查并且 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();
}
}