如何使用 Java 发出多部分/表单数据 POST 请求?

在 Apache Commons HttpClient 的3.x 版本时代,可以进行多部分/表单数据的 POST 请求(2004年的一个例子)。不幸的是,这在 HttpClient 的4.0版本中不再可能。

For our core activity "HTTP", multipart is somewhat 我们喜欢使用多部分代码 其他项目,但我不知道有任何。 几年来,我们试图将多部分代码转移到 commons-codec 但我没有去那里,奥列格最近提到了另一个 具有多部分解析代码并且可能感兴趣的 在我们的多部分格式化代码。我不知道目前的状态 (http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html)

有人知道有哪个 Java 库允许我编写一个 HTTP 客户端来发出多部分/表单数据 POST 请求吗?

背景: 我想使用 Zoho Writer 的远程 API

363032 次浏览

We use HttpClient 4.x to make multipart file post.

更新 : 从 HttpClient 4.3开始,一些类已被弃用:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = new HttpPost("...");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("field1", "yes", ContentType.TEXT_PLAIN);


// This attaches the file to the POST:
File f = new File("[/path/to/upload]");
builder.addBinaryBody(
"file",
new FileInputStream(f),
ContentType.APPLICATION_OCTET_STREAM,
f.getName()
);


HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
CloseableHttpResponse response = httpClient.execute(uploadFile);
HttpEntity responseEntity = response.getEntity();

下面是 已废弃的 HttpClient 4.0 API的原始代码片段:

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);


FileBody bin = new FileBody(new File(fileName));
StringBody comment = new StringBody("Filename: " + fileName);


MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("bin", bin);
reqEntity.addPart("comment", comment);
httppost.setEntity(reqEntity);


HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();

httpcomponents-client-4.0.1对我来说很有用,但是我必须添加外部的罐子 apache-mime4j-0.6.jar(Org.apache.james.ime4j) reqEntity.addPart("bin", bin);无法编译,现在它运行得很好。

These are the Maven dependencies I have.

Java 代码:

HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);


FileBody uploadFilePart = new FileBody(uploadFile);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("upload-file", uploadFilePart);
httpPost.setEntity(reqEntity);


HttpResponse response = httpclient.execute(httpPost);

Xml 中的 Maven 依赖项:

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.0.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.0.1</version>
<scope>compile</scope>
</dependency>

你也可以使用构建在 HTTP 客户端上的 休息放心,它非常简单:

given().multiPart(new File("/somedir/file.bin")).when().post("/fileUpload");

If size of the JARs matters (e.g. in case of applet), one can also directly use httpmime with java.net.HttpURLConnection instead of HttpClient.

httpclient-4.2.4:      423KB
httpmime-4.2.4:         26KB
httpcore-4.2.4:        222KB
commons-codec-1.6:     228KB
commons-logging-1.1.1:  60KB
Sum:                   959KB


httpmime-4.2.4:         26KB
httpcore-4.2.4:        222KB
Sum:                   248KB

密码:

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");


FileBody fileBody = new FileBody(new File(fileName));
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT);
multipartEntity.addPart("file", fileBody);


connection.setRequestProperty("Content-Type", multipartEntity.getContentType().getValue());
OutputStream out = connection.getOutputStream();
try {
multipartEntity.writeTo(out);
} finally {
out.close();
}
int status = connection.getResponseCode();
...

Xml 中的依赖项:

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.2.4</version>
</dependency>

使用此代码以多部分方式将图像或任何其他文件上传到服务器。

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;


import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;


public class SimplePostRequestTest {


public static void main(String[] args) throws UnsupportedEncodingException, IOException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.0.102/uploadtest/upload_photo");


try {
FileBody bin = new FileBody(new File("/home/ubuntu/cd.png"));
StringBody id = new StringBody("3");
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("upload_image", bin);
reqEntity.addPart("id", id);
reqEntity.addPart("image_title", new StringBody("CoolPic"));


httppost.setEntity(reqEntity);
System.out.println("Requesting : " + httppost.getRequestLine());
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpclient.execute(httppost, responseHandler);
System.out.println("responseBody : " + responseBody);


} catch (ClientProtocolException e) {


} finally {
httpclient.getConnectionManager().shutdown();
}
}


}

it requires below files to upload.

图书馆 httpclient-4.1.2.jar, httpcore-4.1.2.jar, httpmime-4.1.2.jar, httpclient-cache-4.1.2.jar, commons-codec.jarcommons-logging-1.1.1.jar位于类路径中。

我们有一个多部分表单提交的纯 Java 实现,它不使用 jdk 之外的任何外部依赖项或库

private static String body = "{\"key1\":\"val1\", \"key2\":\"val2\"}";
private static String subdata1 = "@@ -2,3 +2,4 @@\r\n";
private static String subdata2 = "<data>subdata2</data>";


public static void main(String[] args) throws Exception{
String url = "https://" + ip + ":" + port + "/dataupload";
String token = "Basic "+ Base64.getEncoder().encodeToString((userName+":"+password).getBytes());


MultipartBuilder multipart = new MultipartBuilder(url,token);
multipart.addFormField("entity", "main", "application/json",body);
multipart.addFormField("attachment", "subdata1", "application/octet-stream",subdata1);
multipart.addFormField("attachment", "subdata2", "application/octet-stream",subdata2);
List<String> response = multipart.finish();
for (String line : response) {
System.out.println(line);
}
}

我在 Apache 的 快速入门指南中找到了 this sample,是4.5版本的:

/**
* Example how to use multipart/form encoded POST request.
*/
public class ClientMultipartFormPost {


public static void main(String[] args) throws Exception {
if (args.length != 1)  {
System.out.println("File path not given");
System.exit(1);
}
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httppost = new HttpPost("http://localhost:8080" +
"/servlets-examples/servlet/RequestInfoExample");


FileBody bin = new FileBody(new File(args[0]));
StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);


HttpEntity reqEntity = MultipartEntityBuilder.create()
.addPart("bin", bin)
.addPart("comment", comment)
.build();




httppost.setEntity(reqEntity);


System.out.println("executing request " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
System.out.println("Response content length: " + resEntity.getContentLength());
}
EntityUtils.consume(resEntity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}

这里有一个不需要任何库的解决方案。

这个例程将目录 d:/data/mpf10中的每个文件传输到 urlToConnect


String boundary = Long.toHexString(System.currentTimeMillis());
URLConnection connection = new URL(urlToConnect).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
File dir = new File("d:/data/mpf10");
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
continue;
}
writer.println("--" + boundary);
writer.println("Content-Disposition: form-data; name=\"" + file.getName() + "\"; filename=\"" + file.getName() + "\"");
writer.println("Content-Type: text/plain; charset=UTF-8");
writer.println();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
for (String line; (line = reader.readLine()) != null;) {
writer.println(line);
}
} finally {
if (reader != null) {
reader.close();
}
}
}
writer.println("--" + boundary + "--");
} finally {
if (writer != null) writer.close();
}
// Connection is lazily executed whenever you request any status.
int responseCode = ((HttpURLConnection) connection).getResponseCode();
// Handle response

我的代码将 multipartFile 发送到服务器。

  public static HttpResponse doPost(
String host,
String path,
String method,
MultipartFile multipartFile
) throws IOException
{


HttpClient httpClient = wrapClient(host);
HttpPost httpPost = new HttpPost(buildUrl(host, path));


if (multipartFile != null) {


HttpEntity httpEntity;


ContentBody contentBody;
contentBody = new ByteArrayBody(multipartFile.getBytes(), multipartFile.getOriginalFilename());
httpEntity = MultipartEntityBuilder.create()
.addPart("nameOfMultipartFile", contentBody)
.build();


httpPost.setEntity(httpEntity);


}
return httpClient.execute(httpPost);
}

我的代码发送文件到服务器使用多部分后。 Make use of multivalue map while making request for sending form data

  LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("FILE", new FileSystemResource(file));
map.add("APPLICATION_ID", Number);


httpService.post( map,headers);


At receiver end use

@RequestMapping(value = "fileUpload", method = RequestMethod.POST)
public ApiResponse AreaCsv(@RequestParam("FILE") MultipartFile file,@RequestHeader("clientId") ){
//code
}

使用 HttpRequestFactory 来 jira xray 的/rest/raven/1.0/import/execute/黄瓜/multipart:

Map<String, Object> params = new HashMap<>();
params.put( "info", "zigouzi" );
params.put(  "result", "baalo"  );
HttpContent content = new UrlEncodedContent(params);


OAuthParameters oAuthParameters = jiraOAuthFactory.getParametersForRequest(ACCESS_TOKEN, CONSUMER_KEY, PRIVATE_KEY);
HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory(oAuthParameters);
HttpRequest request = requestFactory.buildPostRequest(new GenericUrl(url),   content);
request.getHeaders().setAccept("application/json");
String boundary = Long.toHexString(System.currentTimeMillis());
request.getHeaders().setContentType("multipart/form-data; boundary="+boundary);
request.getHeaders().setContentEncoding("application/json");
HttpResponse response = null ;
try
{
response = request.execute();
Scanner s = new Scanner(response.getContent()).useDelimiter("\\A");
result = s.hasNext() ? s.next() : "";
}
catch (Exception e)
{
                 

}

成功了。

你会幸福的!

   <dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3.1</version>
</dependency>


import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;




byte[] byteArr1 = multipartFile1.getBytes();
byte[] byteArr2 = multipartFile2.getBytes();


HttpEntity reqEntity = MultipartEntityBuilder.create().setCharset(Charset.forName("UTF-8"))
.addPart("image1", new ByteArrayBody(byteArr1, req.getMultipartFile1().getOriginalFilename()))
.addPart("image2", new ByteArrayBody(byteArr2, req.getMultipartFile2().getOriginalFilename()))
.build();