Send File with HttpUrlConnection - java

I want to send a file with to an API endpoint. If the Multipart is not required it works fine, but as soon as I enter the File it returns a 400 error.
Endpoint:
#PostMapping(value = "/doc", produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
Response<String> addDoc(HttpServletRequest request,
#Parameter(name = "clientId", required = true,
description = "Client ID")
#RequestParam("clientId") Long clientId,
#Parameter(name = "description", required = true,
description = "Description's file")
#RequestParam("description") String description,
#Parameter(name = "file", required = true,
description = "File")
#RequestParam("file") MultipartFile file
)
Java (f is a File):
String boundary = UUID.randomUUID().toString();
url = new URL("http://172.16.1.33:8498/document/doc?clientId=" + clientId + "&description=" + description;
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("charset", "UTF-8");
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Cache-Control", "no-cache");
conn.setRequestProperty ("Authorization", "Bearer " + tok);
conn.setRequestProperty("Content-Type", "Multipart/Form-Data;boundary=" + boundary);
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes("--" + boundary + "\r\n");
dos.writeBytes("Content-Disposition: Form-Data; name=\"file\"; filename=\"" + f.getName() + "\"\r\n\r\n");
dos.write(Files.readAllBytes(f.toPath()));
dos.writeBytes("\r\n");
dos.writeBytes("--" + boundary + "--\r\n");
dos.flush();
dos.close();
br = new BufferedReader(new InputStreamReader(
conn.getInputStream(), Charset.forName("UTF-8")));

Related

Send Image with Parameters To Server Using HttpURLConnection in android

I am trying to upload two images along with some parameters to a server through my android application. After having searched online and following the instructions from here and here, as well as other sources, I have the following code:
String boundary = "***" + System.currentTimeMillis() + "***";
String twoHyphens = "--";
String crlf = "\r\n";
String output = "";
try {
HttpURLConnection httpUrlConnection = null;
URL url = new URL(myUrl);
httpUrlConnection = (HttpURLConnection) url.openConnection();
httpUrlConnection.setUseCaches(false);
httpUrlConnection.setDoInput(true);
httpUrlConnection.setDoOutput(true);
httpUrlConnection.setRequestMethod("POST");
httpUrlConnection.setRequestProperty("Connection", "Keep-Alive");
httpUrlConnection.setRequestProperty("Cache-Control", "no-cache");
httpUrlConnection.setRequestProperty("ENCTYPE", "multipart/form-data");
httpUrlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream request = new DataOutputStream(httpUrlConnection.getOutputStream());
request.writeBytes(twoHyphens + boundary + crlf);
// Convert and add first image
ByteArrayOutputStream bao1 = new ByteArrayOutputStream();
params[0].compress(Bitmap.CompressFormat.JPEG, 100, bao1);
byte[] ba1 = bao1.toByteArray();
request.writeBytes("Content-Disposition: form-data; name=\"image1\";filename=\"image1\"" + crlf);
request.writeBytes(crlf);
request.write(ba1);
request.writeBytes(crlf);
request.writeBytes(twoHyphens + boundary + crlf);
// Convert and add second image
ByteArrayOutputStream bao2 = new ByteArrayOutputStream();
params[1].compress(Bitmap.CompressFormat.JPEG, 100, bao2);
byte[] ba2 = bao2.toByteArray();
request.writeBytes("Content-Disposition: form-data; name=\"image2\";filename=\"image2\"" + crlf);
request.writeBytes(crlf);
request.write(ba2);
request.writeBytes(crlf);
request.writeBytes(twoHyphens + boundary + crlf);
request.writeBytes("Content-Disposition: form-data; name=\"username\"" + crlf);
request.writeBytes(crlf);
request.writeBytes(username);
request.writeBytes(crlf);
request.writeBytes(twoHyphens + boundary + twoHyphens);
request.writeBytes("Content-Disposition: form-data; name=\"datestr\"" + crlf);
request.writeBytes(crlf);
request.writeBytes(timeStampString);
request.writeBytes(crlf);
request.writeBytes(twoHyphens + boundary + twoHyphens);
request.flush();
request.close();
int responseCode = httpUrlConnection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
InputStream responseStream = new BufferedInputStream(httpUrlConnection.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream, Charset.forName("UTF-8")));
String line;
while ((line = responseStreamReader.readLine()) != null) {
output = line;
Log.d(TAG, line);
}
responseStreamReader.close();
}
httpUrlConnection.disconnect();
if (output == "") {
httpResultsReturned = false;
} else {
httpResultsReturned = true;
}
} catch (ProtocolException e) {
e.printStackTrace();
return "failed";
} catch (MalformedURLException e) {
e.printStackTrace();
return "failed";
} catch (IOException e) {
e.printStackTrace();
return "failed";
}
On the server side I try to access the data as follows:
<?php
if($_SERVER['REQUEST_METHOD'] === 'POST'){
$image1 = $_FILES['image1']['name'];
$image2 = $_FILES['image2']['name'];
$datestr= $_POST['datestr'];
$username= $_POST['username'];
}
?>
Eventually, both images are successfully transmitted, however I cannot send/receive the extra parameters. I receive the responses correctly, but throughout all the php code (there are parts that I omitted in this question), it seems like none of the parameters are sent/received.
In this question, AndroSco shared the solution that worked for him, but in his php file it looks like he only accesses the image and not the parameter...
Since I don't have a lot of experience on this field, I believe that there is probably something very obvious that I do incorrectly/don't do at all!
Any suggestions will be appreciated!
Thanks!
After much frustration, I found the bug in my code. After having imported the two images in the transmitted message and when I wanted to import the other parameters, I wrote the boundary incorrectly. Instead of adding this:
request.writeBytes(twoHyphens + boundary + crlf);
having a new line at the end, I wrote this:
request.writeBytes(twoHyphens + boundary + twoHyphens);
adding two hyphens at the end of the line.
After replacing the twoHyphens with crlf, everything worked nicely!

HttpUrlConnection POST gives 400 Bad Request. All input fields are correct

I am trying a POST API, which works with cURL command or POSTMan. However, sending the same call through HttpURLConnection doesn't work.
Tried URL encoding the request params too. Still no luck. It's probably something wrong with the POST usage for HttpURLConnection.
String url = "CORRECT_URL";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
String urlParameters = "first_name=John&middle_name=Alfred&last_name=Smith&email=john.smith#gmail.com&phone=5555555555&zipcode=90401&dob=1970-01-22&ssn=543-43-4645&driver_license_number=F211165&driver_license_state=CA";
byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
int postDataLength = postData.length;
con.setRequestMethod("POST");
con.setRequestProperty("Authorization", "Basic AUTH_TOKEN=");
con.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty( "charset", "utf-8");
con.setRequestProperty( "Content-Length", Integer.toString( postDataLength ));
con.setUseCaches( false );
try {
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.write(postData);
wr.flush();
wr.close();
}
catch(Exception e) {
System.out.println("Server returned error!");
con.getResponseMessage();
}
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
System.out.println("Response : " + con.getResponseMessage());
byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
...
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.write(postData);
is overkill.
PrintWriter out = new PrintWriter(
new OutputStreamWriter(con.getOutputStream(), "UTF-8")
);
out.print(urlParameters);
should do the job.

How to POST a file along with multiple fields using Java

I need to post a file to the server along with other fields to a webapi. This is the code that I've implemented but it doesn't seem to work.
FileInputStream fileStream = new FileInputStream(file);
b = new byte[(int)file.length()];
fileStream.read(b);
fileName = file.getName();
String crlf = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
URL url = new URL(URL);
connection = (HttpURLConnection)url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setUseCaches( false );
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
DataOutputStream wr = new DataOutputStream( connection.getOutputStream());
wr.writeBytes(twoHyphens+boundary+crlf);
wr.writeBytes("Content-Disposition: form-data; process=\"extractText\";user=\"" + username + "\";pass=\"" + password + "\";filename=\"" + file.getName() + "\";file=\"");
wr.write(b);
wr.writeBytes("\"" + crlf);
wr.writeBytes(crlf);
wr.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
wr.flush();
wr.close();
responseStream = new InputStreamReader(connection.getInputStream());
BufferedReader br = new BufferedReader(responseStream);
strBuff = new StringBuffer();
String s;
while ( ( s = br.readLine() ) != null ) {
strBuff.append(s);
}
br.close();
responseStream.close();
connection.disconnect();
str = strBuff.toString();
data = str;
parser = new JSONParser();
jsonObj = (JSONObject)parser.parse(str);
str = jsonObj.get("status").toString();
None of the data gets posted. Please help.
I'd suggest using an Http client implementation.
for example, this one shows how to do it with Jersey client:
https://stackoverflow.com/a/24647315/3356136
you can also consider other implementations like Apache HttpComponents

Unable to send multipart post, using java, to node.js API server

I've got a Node.js API that uses multer to handle multipart POST requests.
I am able to create a simple HTML form and POST images from there successfully.
I can also use postman to get the request to go through, but the req.file is always undefined on the server when I try to use my java method (below).
Called Method
public static void testPostImage() throws Exception {
String charset = "UTF-8";
String requestURL = "http://localhost:3000/accounts/2/details";
try {
File outputfile = new File(Util.getWorkingDirectory() + "/details");
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
multipart.addFilePart("details", new File(outputfile.getAbsolutePath()));
List<String> response = multipart.finish();
General.println("SERVER REPLIED:");
for (String line : response) {
General.println(line);
}
} catch (IOException ex) {
General.println(ex);
}
}
The MultipartUtility class comes from this tutorial.
The contents of the constructor and 'addFilePart'...
Constructor
public MultipartUtility(String requestURL, String charset)
throws IOException {
this.charset = charset;
// creates a unique boundary based on time stamp
boundary = "===" + System.currentTimeMillis() + "===";
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true); // indicates POST method
httpConn.setDoInput(true);
httpConn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
httpConn.setRequestProperty("User-Agent", "CodeJava Agent");
httpConn.setRequestProperty("Test", "Bonjour");
outputStream = httpConn.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
true);
}
addFilePart
private static final String LINE_FEED = "\r\n";
public void addFilePart(String fieldName, File uploadFile)
throws IOException {
General.println("Sending to " + fieldName + ": " + uploadFile.getAbsolutePath());
// Add boundary
writer.append("--" + boundary).append(LINE_FEED);
// Add form data
writer.append("Content-Disposition: form-data;"
+ "name=\"myFile\";"
+ "filename=\"" + fieldName + "\""
+ "\nContent-Type: text/plain\n\n").append(LINE_FEED);
writer.append("Content-Type: " + "multipart/form-data").append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
writer.append(LINE_FEED);
writer.flush();
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
inputStream.close();
writer.append(LINE_FEED);
writer.flush();
}
Their might be more to it but you don't have the right line ending between your Content-disposition and Content-type header:
// Add form data
writer.append("Content-Disposition: form-data;"
+ "name=\"myFile\";"
+ "filename=\"" + fieldName + "\"").append(LINE_FEED);
writer.append("Content-Type: text/plain").append(LINE_FEED).append(LINE_FEED); // need 2 line feeds
Also you are mixing the order/type of headers
writer.append("Content-Type: " + "multipart/form-data").append(LINE_FEED);
writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);
Should come before your encoded data.
See examples here

Sending a HTTP POST Request

I am trying to send a request to get public transport information. Here's a screenshot of an example below, stating that I must send an XML request to the site, defining the method and the service reference (in the example it's StopMonitoringRequest and 020035811).
So far I have managed to connect to the service, but I have no idea what to do from here. I have so far done this...
String user = "";
String pass = "";
String url = "http://nextbus.mxdata.co.uk/nextbuses/1.0/1";
String authString = user + ":" + pass;
byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
String authStringEnc = new String(authEncBytes);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestProperty("Authorization", "Basic " + authStringEnc);
connection.setRequestMethod("POST");
connection.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty( "charset", "utf-8");
connection.setUseCaches(false);
connection.setDoOutput(true);
InputStream is = connection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
int numCharsRead;
char[] charArray = new char[1024];
StringBuffer sb = new StringBuffer();
while ((numCharsRead = isr.read(charArray)) > 0) {
sb.append(charArray, 0, numCharsRead);
}
String result = sb.toString();
System.out.print(result);
...receiving this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Siri version="1.0" xmlns="http://www.siri.org.uk/">
<ServiceDelivery>
<ResponseTimestamp>2015-11-08T20:33:03.574Z</ResponseTimestamp>
</ServiceDelivery>
</Siri>
How do I enter the required parameters and method?
So what I had to do was create a HttpPost and set the xml request up as an entity, binding it to the post. Here is the code, in case anyone wants to request information via HTTP POST using XML, outputting the XML as a string:
// basic autthorization security
String url = "http://nextbus.mxdata.co.uk/nextbuses/1.0/1";
String authString = "<username>:<password>";
byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
String authStringEnc = new String(authEncBytes);
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
post.setHeader("Authorization", "Basic " + authStringEnc);
StringEntity input = new StringEntity(request);
input.setContentType("text/xml");
post.setEntity(input);
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
String unformattedXML = EntityUtils.toString(entity);

Categories

Resources