HttpURLConnection is Connection reset or Broken pipe - java

I am trying to upload byte array to http server using post method from android. But i am getting always connection reset or Broken pipe error. Could pls help me understand where i am doing wrong.
int bufferBytes = 131072; // 128 KB
Random r = new Random( System.currentTimeMillis() );
int fileName = 10000 + r.nextInt(20000);
String urlParameters = ""+ StringUtils.leftPad("abcdefgh", bufferBytes, "abcdefgh");
byte[] postData = urlParameters.getBytes( StandardCharsets.UTF_8 );
String CRLF = "\r\n";
String boundary = "-----------------------******";
OutputStream out = null;
HttpURLConnection urlConnection = null;
PrintWriter writer = null;
try {
URL url = new URL("host");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setConnectTimeout(10*1000) ; // 15 Sec time out
System.setProperty("http.keepAlive", "false");
urlConnection.setChunkedStreamingMode(1024);
//urlConnection.setRequestProperty("Keep-Alive", "false");
urlConnection.setRequestProperty("connection", "close");
urlConnection.setUseCaches (false);
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Accept", "text/xml,application/x ml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
urlConnection.setConnectTimeout(15*1000) ; // 15 Sec time out
urlConnection.setRequestProperty( "Content-Length", Integer.toString( postData.length ));
urlConnection.setRequestProperty("Accept-Encoding", "identity");
urlConnection.setRequestProperty("Transfer-Encoding", "chunked") ;
urlConnection.connect();
out = urlConnection.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true);
// Send normal param.
writer.append("100000").append(CRLF);
writer.append(boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"success_action_status\"").append(CRLF);
writer.append("201").append(CRLF);
writer.append(boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"Content-Type\"").append(CRLF);
writer.append("image/jpeg").append(CRLF);
writer.append(boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"x-amz-acl\"").append(CRLF);
writer.append("public-read").append(CRLF);
writer.append(boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"key\"").append(CRLF);
writer.append("images/237615.jpg").append(CRLF);
writer.append(boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"FileName\"").append(CRLF);
writer.append("ul+"+fileName+".jpg").append(CRLF);
writer.append(boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"file\"; filename=ul" +fileName).append(CRLF);
writer.append("Content-Type: image/jpeg").append(CRLF); // Text file itself must be saved in this charset!
writer.append(CRLF).flush();
out.flush(); // Important before continuing with writer!
writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.
long startTime = System.currentTimeMillis();
while (true){
out.write(postData);
out.flush();
if(System.currentTimeMillis() - startTime > 10000)
break;
}
Log.d("Upload" , " Upload is success");
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}finally {
try {
if(writer != null)
writer.close();
if(out != null)
out.close();
if(urlConnection != null)
urlConnection.disconnect();
}catch (Exception e){
e.printStackTrace();
}
}
If i comment the below line i am getting the java.net.SocketException: Connection reset else i am getting the java.net.SocketException: Broken pipe
System.setProperty("http.keepAlive", "false");

Don't set the content length. It isn't required at all in chunked transfer mode, and it isn't required at all in Java HttpURLConnection, which sets it for you when necessary.

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!

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

Posting File to WebServer with Java

I'm trying to post a file to a ASP.NET WEB API (C#) Server with a local Java application.
Basically I'm trying to reproduce the following HTML code in Java SE:
<form name="form1" method="post" enctype="multipart/form-data" action="http://localhost:50447/api/files/">
<div>
<label for="image1">Image File</label>
<input name="image1" type="file" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
What's the simplest way to do this? I'd like to avoid using Apache..
Something like:
String urlToConnect = "http://localhost:50447/api/files/";
String paramToSend = "";
File fileToUpload = new File("C:/Users/aa/Desktop/sample_signed.pdf");
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
URLConnection connection = null;
try {
connection = new URL(urlToConnect).openConnection();
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
connection.setDoOutput(true); // This sets request method to POST.
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
writer.println("--" + boundary);
writer.println("Content-Disposition: form-data; name=\"paramToSend\"");
writer.println("Content-Type: text/plain; charset=UTF-8");
writer.println();
writer.println(paramToSend);
writer.println("--" + boundary);
writer.println("Content-Disposition: form-data; name=\"fileToUpload\"; filename=\"sample_signed.pdf\"");
writer.println("Content-Type: text/plain; charset=UTF-8");
writer.println();
BufferedReader reader = null;
try {
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileToUpload), "UTF-8"));
} catch (UnsupportedEncodingException | FileNotFoundException e1) {
e1.printStackTrace();
}
try {
for (String line; (line = reader.readLine()) != null;) {
writer.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
}
writer.println("--" + boundary + "--");
} catch (UnsupportedEncodingException e2) {
e2.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
} finally {
if (writer != null) writer.close();
}
// Connection is lazily executed whenever you request any status.
int responseCode = 0;
try {
responseCode = ((HttpURLConnection) connection).getResponseCode();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(responseCode);
Using only URLConnections.. This code isn't working properly.. It sends the file, but some content is lost and I don't know why.. My HTML sample works perfectly..
Can you help me?
Thank you for your attention,
Best Regards.
You are using a reader and writer combination, while you are transferring binary data. You should use streams when working with binary data.
So instead of a BufferedReader, use a normal InputStream buffered to read the file and do not wrap the output stream you get from the URLConnection.
Read bytes instead of strings in the read loop. So replace the part starting with BufferedReader until the finally just before the boundary write with:
OutputStream output = connection.getOutputStream();
InputStream fileIn = new FileInputStream(fileToUpload);
try {
byte[] buffer = new byte[4096];
int length;
while ((length = fileIn.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.flush();
} finally {
if (fileIn != null) try { fileIn.close(); } catch (IOException logOrIgnore) {}
}
Solution: Another approach, using DataOutputStream.
FileInputStream fileInputStream = new FileInputStream(absolutePath);
URL url = new URL("http://localhost:50447/api/files/");
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE", "multipart/form-data");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("uploaded_file", filename);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\"" + fileName + "\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
serverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn.getResponseMessage();
System.out.println(serverResponseMessage);
fileInputStream.close();
dos.flush();
dos.close();

Why is the Multiform-Upload-Request empty at the server?

I'm trying to upload files and posting some variables via URLConnection and multipart/form-data. But the request is empty at the server.
I've written a very basic PHP script for prototyping the solution. At the moment the code looks like that:
$uploaddir = './uploads/';
$uploadfile = $uploaddir . basename($_FILES['file1']['name']);
if(move_uploaded_file($_FILES['file1']['tmp_name'], $uploadfile)) {
echo 'success ' . $_POST['input1'] . ' ' . $_POST['input2'];
} else {
echo 'error ';
var_dump($_FILES);
echo ' ';
var_dump($_POST);
}
And my Java test code looks like:
URL url = new URL(DEST_URL);
String boundary = "---------------------" + Long.toString(System.currentTimeMillis());
PrintWriter writer = null;
URLConnection con = url.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
OutputStream output = con.getOutputStream();
InputStream input = new FileInputStream(new File(FILE_PATH));
writer = new PrintWriter(new OutputStreamWriter(output));
writer.println(boundary);
writer.println("Content-Disposition: form-data; name=\"input1\"");
writer.println();
writer.println("1234");
writer.flush();
writer.println(boundary);
writer.println("Content-Disposition: form-data; name=\"input1\"");
writer.println();
writer.println("asdf");
writer.flush();
writer.println(boundary);
writer.println("Content-Disposition: form-data; name=\"file1\"; filename=\"clicknpoint.png\"");
writer.println("Content-Type: image/png");
writer.flush();
int length = 0;
byte[] buffer = new byte[1024];
for(length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
input.close();
writer.println();
writer.println(boundary);
writer.flush();
input = con.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String cur = null;
StringBuffer buf = new StringBuffer();
while((cur = reader.readLine()) != null) {
buf.append(cur);
}
System.out.println(buf.toString());
Assert.assertTrue(buf.toString().startsWith("success"));
The test case fails and prints
error array(0) {} array(0) {}
I've inspected the request with wireshark. That's what is sended:
POST /test/upload.php HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------1350394409130
User-Agent: Java/1.6.0_33
Host: localhost
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 94528
---------------------1350394409130
Content-Disposition: form-data; name="input1"
1234
---------------------1350394409130
Content-Disposition: form-data; name="input1"
asdf
---------------------1350394409130
Content-Disposition: form-data; name="file1"; filename="clicknpoint.png"
Content-Type: image/png
.PNG
.
...
IHDR..............d<.....sRGB.........gAMA......a.....pHYs..........o.d....IDATx^..}.FWy......c,UU.....|.($. .B1..4%..(MC. ...(..j..."<.I.dD.&.DD.&q..Y....P..\..v.!..k...1v....m. // and so on
Any idea what's wrong?
THe problem is the invalid boundary. The boundary has to start with extra "--" and the request has to end with "--" + boundary + "--" in it's own line.
That's missing here.

How to upload to image hosting site in java?

I'm trying to upload image to a image hosting site (fastpic.ru) but I can't get right response as I expected. I used fiddler to check would I send right param and everything seems are fine but I can't get right response. Could you guide me how to upload and get response in proper way?
Right response I mean I should receive something like http://fastpic.ru/session/2012/0425/Y6sEtGjtT1.html but I only receive http://fastpic.ru/index.php
Thank you
This is my code
String urlToConnect = "http://fastpic.ru/uploadmulti";
String boundary = Long.toHexString(System.currentTimeMillis()); // Generate random boundary
URLConnection connection = new URL(urlToConnect).openConnection();
connection.setDoOutput(true); // This sets request method to POST.
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
OutputStream output = null;
PrintWriter writer = null;
try {
output = connection.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8"), true); // true = Autoflush, important!
writer.println("-----------------------------" + boundary);
writer.println("Content-Disposition: form-data; name=\"file[]\"; filename=\"" + fileToUpload.getName() + "\"");
writer.println("Content-Type: image/jpeg");
writer.println();
InputStream input = null;
try {
input = new FileInputStream(fileToUpload);
byte[] buffer = new byte[1024];
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
output.flush();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException logOrIgnore) {
}
}
}
writer.println();
writer.println("-----------------------------" + boundary);
writer.println("Content-Disposition: form-data; name=\"submit\"");
writer.println();
writer.println("Загрузить");
writer.println("-----------------------------" + boundary);
writer.println("Content-Disposition: form-data; name=\"uploading\"");
writer.println();
writer.println("1");
writer.println("-----------------------------" + boundary + "--");
} finally {
if (writer != null) {
writer.close();
}
}
BufferedReader in = new BufferedReader(
new InputStreamReader(
connection.getInputStream()));
String decodedString;
while ((decodedString = in.readLine()) != null) {
System.out.println(decodedString);
}
in.close();
If it isn't returning the right output, there is probably something incorrect with the input.
I would recommend using the Apache HTTP components, such as MultipartEntity at http://hc.apache.org/httpcomponents-client-ga/httpmime/apidocs/org/apache/http/entity/mime/MultipartEntity.html for POSTing this kind of data. If you're trying to manually encode your data, it would be quite easy to make a simple mistake that'll stop the entire thing from working. There are a lot of examples using the Apache components, and its pretty simple to use.

Categories

Resources