Send Image with Parameters To Server Using HttpURLConnection in android - java

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!

Related

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

Uploading a bitmap from android to a server results in an unopenable file

So I've used some code from stackoverflow that uses HttpURLConnection to send a bitmap from Android to my local WAMP server. The only issue I have is that the data being sent can't be open by an image viewer. I have a feeling it has to do with the method that I am sending the data.
HttpURLConnection httpUrlConnection = null;
URL url = new URL(ip+urls[0]);
httpUrlConnection = (HttpURLConnection) url.openConnection();
httpUrlConnection.setUseCaches(false);
httpUrlConnection.setDoOutput(true);
httpUrlConnection.setRequestMethod("POST");
httpUrlConnection.setRequestProperty("Connection", "Keep-Alive");
httpUrlConnection.setRequestProperty("Cache-Control", "no-cache");
httpUrlConnection.setRequestProperty(
"Content-Type", "multipart/form-data;boundary=" + this.boundary);
DataOutputStream request = new DataOutputStream(
httpUrlConnection.getOutputStream());
request.writeBytes(this.twoHyphens + this.boundary + this.crlf);
request.writeBytes("Content-Disposition: form-data; name=\"" +
this.attachmentName + "\";filename=\"" +
this.attachmentFileName + "\"" + this.crlf);
request.writeBytes(this.crlf);
int bytes = bitmap.getByteCount();
Log.e("bitmap bytes",Integer.toString(bytes));
ByteBuffer buffer = ByteBuffer.allocate(bytes);
bitmap.copyPixelsToBuffer(buffer);
byte[] pixels = buffer.array();
request.write(pixels);
request.writeBytes(this.crlf);
request.writeBytes(this.twoHyphens + this.boundary +
this.twoHyphens + this.crlf);
request.flush();
request.close();
//Response
InputStream responseStream = new
BufferedInputStream(httpUrlConnection.getInputStream());
BufferedReader responseStreamReader =
new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
responseStreamReader.close();
String response = stringBuilder.toString();
responseStream.close();
httpUrlConnection.disconnect();
return response;
I have checked the file sizes and they are the same. I plan on sending the image back to my android device in the future, however I wanted to make sure the uploading part worked first. If the file is supposed to be unopenable and I'm understanding the code wrong I apologize for the wasted time.

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

Java POSTing File Results In HTTP 422

I'm trying to build a small Java app for connecting to an application called CampFire and am running into trouble trying to upload files to the system. The Java code I'm using to upload a file is as follows:
public static String postFile(String requestUri, File f)
{
debug("Running postFile.");
logIn();
debug("Sending File: " + f.getAbsolutePath() + " to " + campFireURL + requestUri);
URL url;
URLConnection conn;
String linebreak = "\r\n";
String boundary = "**********xxx**********";
String twoHyphens = "--";
String result = "";
String request = twoHyphens + boundary + linebreak +
"Content-Disposition: form-data; name=\"upload\"; filename=\"" + f.getName() + "\"" + linebreak +
linebreak +
"";
debug("Request: " + request);
try
{
FileInputStream in = new FileInputStream(f);
auth.resetTries();
Authenticator.setDefault(auth);
// Send data
url = new URL(campFireURL + requestUri);
conn = url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(request);
int i;
while((i = in.read()) != -1)
{
wr.write(i);
}
wr.writeBytes(linebreak + twoHyphens + boundary + twoHyphens + linebreak);
wr.flush();
wr.close();
in.close();
result = readFromConnection(conn);
}
catch (Exception e)
{
debug(e);
JOptionPane.showMessageDialog(null, "Error running postData: " + e.getMessage(), "HTTP POST Error", JOptionPane.ERROR_MESSAGE);
die();
}
return(result);
}
When I run this with a real file though, I get the following errors...
Running postFile.
Sending File: /home/myuser/Desktop/blah.png to https://blah.campfirenow.com/room/blah/uploads.xml
Request: --**********xxx**********
Content-Disposition: form-data; name="upload"; filename="blah.png"
Server returned HTTP response code: 422 for URL: blah blah
java.io.IOException: Server returned HTTP response code: 422 for URL: blah blah
Any idea's what I'm doing wrong here? I'm fairly new at Java and am wondering if maybe I missed something obvious?
HTTP error 422 means "Unprocessable Entity". After a quick glance I can spot one mistake: a PNG file is a binary file. You've to add Content-Transfer-Encoding: binary to the header of the part.
If it still doesn't work, then you may find the example in the Uploading files section at the bottom of this answer useful.

Best approach: HTTP POST (multi-part) from Android to GAE

I would like to capture an image from the camera on Android, and send it to Google App Engine, which will store the image in the blob store. Sounds simple enough, and I can get the multi-part POST to GAE happening, but storing to the Blob store requires the servlet return an HTTP redirect (302). So, I need a connection that can follow redirects after doing an HTTP POST. Here is the code I WISH would work:
public static String sendPhoto(String myUrl, byte[] imageData) {
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
String pathToOurFile = "/data/file_to_send.jpg";
String urlServer = myUrl;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
// Please follow redirects
HttpURLConnection.setFollowRedirects(true);
BufferedReader rd = null;
StringBuilder sb = null;
String line = null;
try {
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// I really want you to follow redirects
connection.setInstanceFollowRedirects(true);
connection.setConnectTimeout(10000); // 10 sec
connection.setReadTimeout(10000); // 10 sec
// Enable POST method
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
connection.connect();
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream
.writeBytes("Content-Disposition: form-data; name="
+ "\"file1\";filename=\""
+ pathToOurFile + "\"" + lineEnd);
outputStream.writeBytes(lineEnd);
outputStream.write(imageData);
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens
+ lineEnd);
outputStream.flush();
outputStream.close();
rd = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
sb = new StringBuilder();
while ((line = rd.readLine()) != null) {
sb.append(line + '\n');
}
Log.i("Response: ", sb.toString());
// Responses from the server (code and message)
int serverResponseCode = connection.getResponseCode();
String serverResponseMessage = connection.getResponseMessage();
Log.i("Response: serverResponseCode:",
String.valueOf(serverResponseCode));
Log.i("Response: serverResponseMessage:", serverResponseMessage);
} catch (Exception ex) {
ex.printStackTrace();
}
}
As much as I try, this code will not follow redirects. The input steam is always empty, and the response is always 302. The image is uploaded nicely though. If someone could tell me what I can do to make it follow the redirect so I can read the response, I would really appreciate it.
Alternatively, if there is a better approach, I would love to hear it. I know there are libraries out there like Apache HTTP Client, but it requires so many dependencies that is seems like too much bloat for a simple task.
Thanks
A few months ago I was trying to do the exact same thing!
Basically, don't use HttpURLConnection. Instead, use HttpClient and HttpGet in the org.apache.http package which are part of the Android SDK.
Unfortunately I don't have my source code to provide an example, but hopefully that'll set you in the right direction.
not sure what went wrong, but you can follow redirect yourself. take the Location header out and make a new connection to it.

Categories

Resources