Java Proxy POST request to secondary server - java

Here is the code I have so far.
What does works is reading all form name/values from the original request.
What does not work is the new server does not receive any of the newly assigned form name/values. Basically they dont seem to get transmitted to the secondary server.
There might be an easier way to do so?? All I need is to trigger on a specific form field from the new server and redirect to a sub-server that will handle the request and pass back the results thru the main server to the client (proxying).
String value = String.format("https://%s.myotherserver.com%s", "sub1", request.getRequestURI());
HttpPost uploadFile = new HttpPost(value);
uploadFile.addHeader("Content-Type", request.getContentType());
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
ContentBody cbFile = new InputStreamBody(request.getPart("audio").getInputStream(), ContentType.create("audio/webm"),"audio.ogg");
builder.addPart("audio", cbFile);
builder.addPart("text", new StringBody(request.getParameter("text"),ContentType.DEFAULT_TEXT));
builder.addPart("email", new StringBody(request.getParameter("email"),ContentType.DEFAULT_TEXT));
// now add the other original form name/values to new request
do
{
String parameterName = reqParameterNames.nextElement().toString();
Object parameterValue = request.getParameter(parameterName);
if (!privateParameters.contains("p_"+parameterName)) {
builder.addPart(new FormBodyPart(parameterName, new StringBody((String) parameterValue,ContentType.DEFAULT_TEXT)));
}
} while (reqParameterNames.hasMoreElements());
HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
CloseableHttpClient httpClient2 = HttpClients.createDefault();
CloseableHttpResponse statusCode = httpClient2.execute(uploadFile);
HttpEntity responseEntity = statusCode.getEntity();
StringBuffer responseBuffer = new StringBuffer();
OutputStream output = response.getOutputStream();
ByteStreams.copy(responseEntity.getContent(), output);
output.flush();

I finally managed to get it to work with the following code. I hope this can help someone else;
MultipartEntityBuilder mb = null;
org.apache.http.HttpEntity entity =null;
String value = String.format("https://%s.myotherserver.com%s", "sub1", request.getRequestURI());
mb = MultipartEntityBuilder.create();
mb.addTextBody("noproxy", "true");
mb.addTextBody("text", request.getParameter("text"));
mb.addTextBody("email", request.getParameter("email"));
mb.addBinaryBody("audio", new File(inputAudioFilename));
entity = mb.build();
URLConnection conn = new URL(urlStr[i]).openConnection();
conn.setDoOutput(true);
conn.addRequestProperty(entity.getContentType().getName(), entity.getContentType().getValue());
conn.addRequestProperty("Content-Length", String.valueOf(entity.getContentLength()));
OutputStream fout = conn.getOutputStream();
entity.writeTo(fout);//write multi part data...
fout.flush();
fout.close();
OutputStream output = response.getOutputStream();
output.flush();
ByteStreams.copy(conn.getInputStream(),response.getOutputStream());
conn.getInputStream().close();

Related

Upload File from GWT to another domain , response is always null

I am uploading a File from GWT to a different domain
File Uploads well , But the response i sent from the server always reaches as "null" at the client side
response.setContentType("text/html");
response.setHeader("Access-Control-Allow-Origin", "*");
response.getWriter().print("TEST");
response is NULL only when i upload the file on a different domain ... (on same domain all is OK)
I also see this in GWT documentation
Tip:
The result html can be null as a result of submitting a form to a different domain.
http://www.gwtproject.org/javadoc/latest/com/google/gwt/user/client/ui/FormPanel.SubmitCompleteEvent.html
Is there any way I can receive back a response at my client side when i am uploading file to a different domain
There are 2 possible answer:
Use JSONP Builder
JsonpRequestBuilder requestBuilder = new JsonpRequestBuilder();
requestBuilder.requestObject(url, new AsyncCallback<FbUser>() {
#Override
public void onFailure(Throwable ex) {
throw SOMETHING_EXCEPTION(ex);
}
#Override
public void onSuccess(ResponseModel resp) {
if (resp.isError()) {
// on response error on something
log.error(resp.getError().getMessage())
log.error(resp.getError().getCode())
}
log.info(resp.getAnyData())
}
Not to use GWT to upload, rather use other client like apache HttpClient
public uploadFile() {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
FileBody bin = new FileBody(new File(UPLOADED_FILE));
long size = bin.getContentLength();
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("PART", bin);
String content = "-";
try {
httpPost.setEntity(reqEntity);
HttpResponse response = httpClient.execute(httpPost, localContext);
HttpEntity ent = response.getEntity();
InputStream st = ent.getContent();
StringWriter writer = new StringWriter();
IOUtils.copy(st, writer);
content = writer.toString();
} catch (IOException e) {
return "false";
}
return content;
}
Hope it helps

How to convert this cUrl command to java containing form and binary data [duplicate]

In the days of version 3.x of Apache Commons HttpClient, making a multipart/form-data POST request was possible (an example from 2004). Unfortunately this is no longer possible in version 4.0 of HttpClient.
For our core activity "HTTP", multipart is somewhat
out of scope. We'd love to use multipart code maintained by some
other project for which it is in scope, but I'm not aware of any.
We tried to move the multipart code to commons-codec a few years
ago, but I didn't take off there. Oleg recently mentioned another
project that has multipart parsing code and might be interested
in our multipart formatting code. I don't know the current status
on that. (http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html)
Is anybody aware of any Java library that allows me to write an HTTP client that can make a multipart/form-data POST request?
Background: I want to use the Remote API of Zoho Writer.
We use HttpClient 4.x to make multipart file post.
UPDATE: As of HttpClient 4.3, some classes have been deprecated. Here is the code with new API:
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();
Below is the original snippet of code with deprecated 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();
These are the Maven dependencies I have.
Java Code:
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);
Maven Dependencies in pom.xml:
<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>
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
Code:
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();
...
Dependency in pom.xml:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.2.4</version>
</dependency>
Use this code to upload images or any other files to the server using post in multipart.
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.
libraries are
httpclient-4.1.2.jar,
httpcore-4.1.2.jar,
httpmime-4.1.2.jar,
httpclient-cache-4.1.2.jar,
commons-codec.jar and
commons-logging-1.1.1.jar to be in classpath.
Here's a solution that does not require any libraries.
This routine transmits every file in the directory d:/data/mpf10 to 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
You can also use REST Assured which builds on HTTP Client. It's very simple:
given().multiPart(new File("/somedir/file.bin")).when().post("/fileUpload");
httpcomponents-client-4.0.1 worked for me. However, I had to add the external jar apache-mime4j-0.6.jar (org.apache.james.mime4j) otherwise
reqEntity.addPart("bin", bin); would not compile. Now it's working like charm.
I found this sample in Apache's Quickstart Guide. It's for version 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();
}
}
}
You will happy!
<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();
We have a pure java implementation of multipart-form submit without using any external dependencies or libraries outside jdk. Refer https://github.com/atulsm/https-multipart-purejava/blob/master/src/main/java/com/atul/MultipartPure.java
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);
}
}
My code post multipartFile to server.
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);
}
My code for sending files to server using post in multipart.
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
}
Using HttpRequestFactory to jira xray's /rest/raven/1.0/import/execution/cucumber/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)
{
}
did the trick.

Send an image from Google Glass to a HTTP server [duplicate]

In the days of version 3.x of Apache Commons HttpClient, making a multipart/form-data POST request was possible (an example from 2004). Unfortunately this is no longer possible in version 4.0 of HttpClient.
For our core activity "HTTP", multipart is somewhat
out of scope. We'd love to use multipart code maintained by some
other project for which it is in scope, but I'm not aware of any.
We tried to move the multipart code to commons-codec a few years
ago, but I didn't take off there. Oleg recently mentioned another
project that has multipart parsing code and might be interested
in our multipart formatting code. I don't know the current status
on that. (http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html)
Is anybody aware of any Java library that allows me to write an HTTP client that can make a multipart/form-data POST request?
Background: I want to use the Remote API of Zoho Writer.
We use HttpClient 4.x to make multipart file post.
UPDATE: As of HttpClient 4.3, some classes have been deprecated. Here is the code with new API:
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();
Below is the original snippet of code with deprecated 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();
These are the Maven dependencies I have.
Java Code:
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);
Maven Dependencies in pom.xml:
<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>
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
Code:
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();
...
Dependency in pom.xml:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.2.4</version>
</dependency>
Use this code to upload images or any other files to the server using post in multipart.
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.
libraries are
httpclient-4.1.2.jar,
httpcore-4.1.2.jar,
httpmime-4.1.2.jar,
httpclient-cache-4.1.2.jar,
commons-codec.jar and
commons-logging-1.1.1.jar to be in classpath.
Here's a solution that does not require any libraries.
This routine transmits every file in the directory d:/data/mpf10 to 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
You can also use REST Assured which builds on HTTP Client. It's very simple:
given().multiPart(new File("/somedir/file.bin")).when().post("/fileUpload");
httpcomponents-client-4.0.1 worked for me. However, I had to add the external jar apache-mime4j-0.6.jar (org.apache.james.mime4j) otherwise
reqEntity.addPart("bin", bin); would not compile. Now it's working like charm.
I found this sample in Apache's Quickstart Guide. It's for version 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();
}
}
}
You will happy!
<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();
We have a pure java implementation of multipart-form submit without using any external dependencies or libraries outside jdk. Refer https://github.com/atulsm/https-multipart-purejava/blob/master/src/main/java/com/atul/MultipartPure.java
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);
}
}
My code post multipartFile to server.
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);
}
My code for sending files to server using post in multipart.
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
}
Using HttpRequestFactory to jira xray's /rest/raven/1.0/import/execution/cucumber/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)
{
}
did the trick.

Get xml response from httpmultipart request

I have a webservice that receibes a files with multipart (In c#), when i send a big file(15MB) by a chrome extension(Advanced Rest extension) the file uploads ok and i can see the body response:
<response xmlns="http://schemas.datacontract.org" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Descripcion>blabla</Descripcion>
<Resultado>-9999</Resultado>
<Servicio xmlns:a="http://schemas.datacontract.org" i:nil="true" />
</reponse>
But when i call with android i get the headers with an 200 code OK response but i dont know how can i get the body response:
This is my code:
/****** Informacion exif *****/
DefaultHttpClient mHttpClient;
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
mHttpClient = new DefaultHttpClient(params);
HttpPost httppost = new HttpPost("HTTPS://SERVICIO.SVC");
httppost.setHeader("Connection", "Keep-Alive");
httppost.setHeader("SOAPAction", "http://tempuri.org/Service1");
httppost.setHeader("identificadorGUID", Guid);
httppost.setHeader("numeroServicio", codigoServicio);
httppost.setHeader("coordenadaLatitud", latitud);
httppost.setHeader("coordenadaLongitud", longitud);
if (QUEES == 0) {
extension = "jpg";
}
if (QUEES == 1) {
extension = "mp4";
}
httppost.setHeader("cuando", cuando);
httppost.setHeader("tipoMultimedia", String.valueOf(tipoMultimedia));
httppost.setHeader("extension", extension);
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
FileBody fileBody = new FileBody(fichero, "multipart/form-data");
multipartEntity.addPart("image", fileBody);
httppost.setEntity(multipartEntity);
try {
HttpResponse response = mHttpClient.execute(httppost);
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
resEntity.consumeContent();
}
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
httppost.getAllHeaders();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
Log.i("Respuesta web service", sResponse);
}
catch (ClientProtocolException e1) {
e1.printStackTrace();
}
catch (IOException e1) {
e1.printStackTrace();
}
Crash with: java.io.IOException: Attempted read from closed stream.
How can i get the response to parse it?
Thanks
Looks like you shouldn't be calling consumeContent() until the information is read (given that it closes the stream). If you're using 4.1 or later, this method has been deprecated, and you should be using EntityUtils.consume(HttpEntity)
From its javadoc:
This method is called to indicate that the content of this entity is no longer required. All entity implementations are expected to release all allocated resources as a result of this method invocation. Content streaming entities are also expected to dispose of the remaining content, if any. Wrapping entities should delegate this call to the wrapped entity.

How do I write to an OutputStream using DefaultHttpClient?

How do I get an OutputStream using org.apache.http.impl.client.DefaultHttpClient?
I'm looking to write a long string to an output stream.
Using HttpURLConnection you would implement it like so:
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
OutputStream out = connection.getOutputStream();
Writer wout = new OutputStreamWriter(out);
writeXml(wout);
Is there a method using DefaultHttpClient similar to what I have above? How would I write to an OutputStream using DefaultHttpClient instead of HttpURLConnection?
e.g
DefaultHttpClient client = new DefaultHttpClient();
OutputStream outstream = (get OutputStream somehow)
Writer wout = new OutputStreamWriter(out);
I know that another answer has already been accepted, just for the record this is how one can write content out with HttpClient without intermediate buffering in memory.
AbstractHttpEntity entity = new AbstractHttpEntity() {
public boolean isRepeatable() {
return false;
}
public long getContentLength() {
return -1;
}
public boolean isStreaming() {
return false;
}
public InputStream getContent() throws IOException {
// Should be implemented as well but is irrelevant for this case
throw new UnsupportedOperationException();
}
public void writeTo(final OutputStream outstream) throws IOException {
Writer writer = new OutputStreamWriter(outstream, "UTF-8");
writeXml(writer);
writer.flush();
}
};
HttpPost request = new HttpPost(uri);
request.setEntity(entity);
You can't get an OutputStream from BasicHttpClient directly. You have to create an HttpUriRequest object and give it an HttpEntity that encapsulates the content you want to sent. For instance, if your output is small enough to fit in memory, you might do the following:
// Produce the output
ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(out, "UTF-8");
writeXml(writer);
// Create the request
HttpPost request = new HttpPost(uri);
request.setEntity(new ByteArrayEntity(out.toByteArray()));
// Send the request
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(request);
If the data is large enough that you need to stream it, it becomes more difficult because there's no HttpEntity implementation that accepts an OutputStream. You'd need to write to a temp file and use FileEntity or possibly set up a pipe and use InputStreamEntity
EDIT See oleg's answer for sample code that demonstrates how to stream the content - you don't need a temp file or pipe after all.
This worked well on android. It should also work for large files, as no buffering is needed.
PipedOutputStream out = new PipedOutputStream();
PipedInputStream in = new PipedInputStream();
out.connect(in);
new Thread() {
#Override
public void run() {
//create your http request
InputStreamEntity entity = new InputStreamEntity(in, -1);
request.setEntity(entity);
client.execute(request,...);
//When this line is reached your data is actually written
}
}.start();
//do whatever you like with your outputstream.
out.write("Hallo".getBytes());
out.flush();
//close your streams
I wrote an inversion of Apache's HTTP Client API [PipedApacheClientOutputStream] which provides an OutputStream interface for HTTP POST using Apache Commons HTTP Client 4.3.4.
Calling-code looks like this:
// Calling-code manages thread-pool
ExecutorService es = Executors.newCachedThreadPool(
new ThreadFactoryBuilder()
.setNameFormat("apache-client-executor-thread-%d")
.build());
// Build configuration
PipedApacheClientOutputStreamConfig config = new
PipedApacheClientOutputStreamConfig();
config.setUrl("http://localhost:3000");
config.setPipeBufferSizeBytes(1024);
config.setThreadPool(es);
config.setHttpClient(HttpClientBuilder.create().build());
// Instantiate OutputStream
PipedApacheClientOutputStream os = new
PipedApacheClientOutputStream(config);
// Write to OutputStream
os.write(...);
try {
os.close();
} catch (IOException e) {
logger.error(e.getLocalizedMessage(), e);
}
// Do stuff with HTTP response
...
// Close the HTTP response
os.getResponse().close();
// Finally, shut down thread pool
// This must occur after retrieving response (after is) if interested
// in POST result
es.shutdown();
Note - In practice the same client, executor service, and config will likely be reused throughout the life of the application, so the outer prep and close code in the above example will likely live in bootstrap/init and finalization code rather than directly inline with the OutputStream instantiation.

Categories