multipart file-upload post request from java - java

I'm trying to make a program that uploads a image to a webserver that accepts multipart file-uploads.
More specificly i want to make a http POST request to http://iqs.me that sends a file in the variable "pic".
I've made a lot of tries but i don't know if i've even been close. The hardest part seems to be to get a HttpURLConnection to make a request of the type POST. The response i get looks like it makes a GET.
(And i want to do this without any third party libs)
UPDATE: non-working code goes here (no errors but doesn't seem to do a POST):
HttpURLConnection conn = null;
BufferedReader br = null;
DataOutputStream dos = null;
DataInputStream inStream = null;
InputStream is = null;
OutputStream os = null;
boolean ret = false;
String StrMessage = "";
String exsistingFileName = "myScreenShot.png";
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1*1024*1024;
String responseFromServer = "";
String urlString = "http://iqs.local.com/index.php";
try{
FileInputStream fileInputStream = new FileInputStream( new File(exsistingFileName) );
URL url = new URL(urlString);
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
dos = new DataOutputStream( conn.getOutputStream() );
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"pic\";" + " filename=\"" + exsistingFileName +"\"" + lineEnd);
dos.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
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);
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
fileInputStream.close();
dos.flush();
dos.close();
}catch (MalformedURLException ex){
System.out.println("Error:"+ex);
}catch (IOException ioe){
System.out.println("Error:"+ioe);
}
try{
inStream = new DataInputStream ( conn.getInputStream() );
String str;
while (( str = inStream.readLine()) != null){
System.out.println(str);
}
inStream.close();
}catch (IOException ioex){
System.out.println("Error: "+ioex);
}

Two things:
Make sure you call setRequestMethod to set the HTTP request to be a POST. You should be warned that doing multipart POST requests by hand is difficult and error-prone.
If you're running on *NIX, the tool netcat is very useful for debugging this stuff. Run
netcat -l -p 3000
and point your program to port 3000; you'll see exactly what the program is sending (Control-C to close it afterwards).

I have used this and found it useful in multipart file upload
File f = new File(filePath);
PostMethod filePost = new PostMethod(url);
Part[] parts = { new FilePart("file", f) };
filePost.setRequestEntity(new MultipartRequestEntity(parts,
filePost.getParams()));
HttpClient client = new HttpClient();
status = client.executeMethod(filePost);

Related

Image upload failure over specific network from only android

We are working on uploading image to our server from android device. Image is successfully uploading in server while using both mobile data and Wi-Fi, except one particular network which we are currently using. This new network setup don’t let pass any data from client end which has greater MTU size than 1460. So, all the packets from android device are rejected and cannot reach the server. Our iOS app can upload image to same server successfully with same network. We have found with tracing that iOS reduces the packet or chunk size if one packet is not successfully sent. But android devices are not behaving like that. We have also found that some social networking android apps can successfully upload image with our network. Some would probably say to change our network with correct settings, but we don’t want to do that as if we can have a defective network, some other people can also have that, where our android app will not work properly.
The works we have tried so far (all of which are working, except the new network) are given below:
Main code which we were using from first:
private boolean uploadImage(String fileLoc, String title){
try {
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
URL connectURL;
connectURL = new URL(baseUrlString); // our server url to upload image
FileInputStream fileInputStream = new FileInputStream(fileLoc);
// ------------------ CLIENT REQUEST
// Open a HTTP connection to the URL
HttpURLConnection conn = (HttpURLConnection) connectURL
.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
//conn.setChunkedStreamingMode(512);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
//conn.setFixedLengthStreamingMode(137931);
DataOutputStream dos = new DataOutputStream(
conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\""
+ param1 + "\"" + lineEnd
+ lineEnd
+ title
+ lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\""
+ fileLoc
+ "\""
+ lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];
// read file and write it into form...
int 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);
// close streams
fileInputStream.close();
dos.flush();
InputStream is = conn.getInputStream();
// retrieve the response from server
int ch;
StringBuffer b = new StringBuffer();
while ((ch = is.read()) != -1) {
b.append((char) ch);
}
String response;
response = b.toString().trim();
dos.close();
// here some work with response
return sucs;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
Here we have also tried with
conn.setChunkedStreamingMode(512);
conn.setRequestProperty("Transfer-Encoding", "chunked");
to limit the chunk size, but it is ignored as the documentation says it is only a hint.
We have also tried with
conn.setFixedLengthStreamingMode(calculatedValueOfbytesForSameImage);
but failed.
Then we tried to implement other methods found in the web using Multipart and Socket:
https://stackoverflow.com/a/16529053/1246639
https://stackoverflow.com/a/19188010/1246639
https://stackoverflow.com/a/22803149/1246639
https://groups.google.com/forum/#!msg/android-developers/SZ5MzO6wr6I/Ol4ZL1Au3U0J
All methods working except our network. Have also tried combining Multipart to ByteArrayOutputStream as https://stackoverflow.com/a/10225966/1246639. But still not working.
Is there any other method available to control the chunk size using other class like the InterfaceAddress or native support or if we are missing something in methods tried above? Thanks.....

Android: java.lang.IllegalStateException: Already connected

I'm testing a sample of code but its always error at connection.setDoInput(true);
HttpsURLConnection connection = null;
DataOutputStream outputStream = null;
DataInputStream inputStream = null;
String urlServer = "https://www.myurl.com/upload.php";
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead = 0;
int bytesAvailable = 0;
int bufferSize = 0;
byte[] buffer = null;
int maxBufferSize = 1*1024*1024;
try {
FileInputStream fileInputStream = new FileInputStream(new File(params[0]));
URL url = new URL(urlServer);
connection = (HttpsURLConnection) url.openConnection();
connection.setConnectTimeout(1000);
// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// Enable POST method
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
connection.setConnectTimeout(1000);
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + params[0] + "\"" + lineEnd);
outputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
The error log is java.lang.IllegalStateException: Already connected.
I have tried these but none is working:
connection.setRequestProperty("Connection", "close");
connection.disconnect();
connection.setConnectTimeout(1000);
EDIT: even when i didn't call connection.connect(), it's still giving the same error already connected.
You must close the input stream after reading it to end of stream.
You should remove the call to connect(). You have it in the wrong place, but it's automatic and doesn't need to be called at all.
You can also remove the line that sets POST. This is implicit in calling setDoOutput(true).
You can also remove most of that crud in the copy loop. Use a fixed size buffer:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Do not use a new buffer per read; do not call available(); do not pass GO; do not collect $200.
Move
connection.connect();
after
connection.setRequestMethod("POST");
There is a very good post about http connections here
The bottom line is that for POSTs you only need the following.
HttpURLConnection connection = (HttpURLConnection) new URL(urlToRead).openConnection();
// setDoOutput(true) implicitly set's the request type to POST
connection.setDoOutput(true);
I'm not sure you need to specify HttpsURLConnection either. You can use HttpURLConnection for connecting to Https sites. Let java do the work for you behind the scenes.
Here is the POST code that I use for json posts
public static String doPostSync(final String urlToRead, final String content) throws IOException {
final String charset = "UTF-8";
// Create the connection
HttpURLConnection connection = (HttpURLConnection) new URL(urlToRead).openConnection();
// setDoOutput(true) implicitly set's the request type to POST
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-type", "application/json");
// Write to the connection
OutputStream output = connection.getOutputStream();
output.write(content.getBytes(charset));
output.close();
// Check the error stream first, if this is null then there have been no issues with the request
InputStream inputStream = connection.getErrorStream();
if (inputStream == null)
inputStream = connection.getInputStream();
// Read everything from our stream
BufferedReader responseReader = new BufferedReader(new InputStreamReader(inputStream, charset));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = responseReader.readLine()) != null) {
response.append(inputLine);
}
responseReader.close();
return response.toString();
}
Add
if (connection != null) connection.disconnect();
before
connection = (HttpsURLConnection) url.openConnection();
See if problem solved. If yes, it means connection.disconnect() is not called in your original code. Maybe you put connection.disconnect() at the end of your try block, however an exception occurs before it, so it jumps to the catch block and connection.disconnect() is never called.

Multipart upload of image in Java

I am trying to attach files through Java code to http://example.com:8080/attachments. I am using multipart data upload. I tried with uploading text files and its working fine. When I tried jpg files the response code is 200, but the uploaded file is having some problems. It says the file is corrupted.
The code for converting the image to byte array.
byte[] bFile = new byte[(int) file.length()];
fileInputStream = new FileInputStream(file);
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 4096;
byte[] buffer = new byte[bytesAvailable];
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);
while (bytesRead > 0) {
bos.write(buffer, 0, bytesAvailable);
bytesAvailable = fileInputStream.available();
bytesAvailable = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);
}
bFile = bos.toByteArray();
The code for uploading
String contentDisposition = "Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"";
String contentType = "Content-Type: image/jpg";
String BOUNDARY = "*****";
HttpsURLConnection connection;
String CRLF = "\r\n";
StringBuffer requestBody = new StringBuffer();
requestBody.append("--");
requestBody.append(BOUNDARY);
requestBody.append(CRLF);
requestBody.append(contentDisposition);
requestBody.append(CRLF);
requestBody.append(contentType);
requestBody.append(CRLF);
requestBody.append(CRLF);
requestBody.append(new String(bFile));
requestBody.append(CRLF);
requestBody.append("--");
requestBody.append(BOUNDARY);
requestBody.append("--");
URL obj = new URL("url");
connection = (HttpsURLConnection) obj.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
connection.setRequestProperty("Accept","*/*");
connection.setRequestProperty("Authorization", strEncoded);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(requestBody.toString());
wr.flush();
wr.close();
Please let me know if there is any problem with the byte array I am sending for images.
Please check the screen shot attached for the error message.
http://tinypic.com/r/33233hl/5
Thanks.
Your code for reading file bytes is error-prone, have a look at the answers for this question.
You can not just add the bytes in the request-body with
requestBody.append(new String(bFile));
This will convert the image bytes to characters which is not what you want - you need the bytes transferred as you read them from the image-file.
Instead of doing this manually, use something like Apache HttpClient. It makes takes care of details like properly putting file-bytes in an http-post. See the official example or see the code in this question.

Server side code to handle HttpURLConnection in Android

I am using HttpURLConnection class to upload text file to my Apache server. For server side code I used php to handle the POST request. I was wondering , how the same thing can be done other then PHP, or the PHP is the best way to handle file uploading on server side?..Also I cannot find any jsp or java code on server side to handle http post request..any code snippet that does same thing other then PHP would be really helpful..Cause I think java or jsp would be easier to code ..Thanks
Android code to upload file:
public void upLoad()
{
String exsistingFileName = path+"//"+"test.txt";
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
try {
// ------------------ CLIENT REQUEST
Log.e(Tag, "Inside second Method");
FileInputStream fileInputStream = new FileInputStream(new File(
exsistingFileName));
// open a URL connection to the Servlet
URL url = new URL(urlString);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: post-data; name=uploadedfile;filename="
+ exsistingFileName + "" + lineEnd);
dos.writeBytes(lineEnd);
Log.e(Tag, "Headers are written");
// create a buffer of maximum size
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1000;
// int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bytesAvailable];
// read file and write it into form...
int bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);
while (bytesRead > 0) {
dos.write(buffer, 0, bytesAvailable);
bytesAvailable = fileInputStream.available();
bytesAvailable = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bytesAvailable);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// close streams
Log.e(Tag, "File is written");
fileInputStream.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
Log.e(Tag, "error: " + ex.getMessage(), ex);
}
catch (IOException ioe) {
Log.e(Tag, "error: " + ioe.getMessage(), ioe);
}
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(conn
.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
Log.e("Dialoge Box", "Message: " + line);
}
rd.close();
} catch (IOException ioex) {
Log.e("MediaPlayer", "error: " + ioex.getMessage(), ioex);
}
}
Php code on server side :
<?php
$target_path = "./upload/";
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file ". basename( $_FILES['uploadedfile']['name']).
" has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
?>
I think there is no correct answer for this question, PHP can be good as JSP or even ASP. Depends on your platform preference or if you are planning on having a tomcat vs apache server or even a microsoft iis server. Personally I think PHP/Apache is a good choice.

How do I add REQUEST values to an HTTP POST method using multipart to upload a file to a PHP server in Android?

So, I'm trying to upload a file to my PHP server. I found some code online which works, but I also need to include values for things like user authentication and where on the server the file should be uploaded. I am relatively new to HTTP communication and the code I found below uses terms/code that I have never heard of before, multipart/form-data Content-Type and Content-Disposition specifically. So if someone could tell me how to include the values I need, provide a different method entirely, or just explain those 3 terms to me like I'm five, I'd greatly appreciate it. Here's my code:
public static void upload(String path, String section, Context c){
Log.i("path", path);
HttpURLConnection conn = null;
DataOutputStream dos = null;
DataInputStream inStream = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
String responseFromServer = "";
String urlString = c.getString(R.string.server) + "upload.php";
try {
// ------------------ CLIENT REQUEST
FileInputStream fileInputStream = new FileInputStream(new File(
path));
// open a URL connection to the Servlet
URL url = new URL(urlString);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
+ path + "\"" + 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);
// close streams
Log.e("Debug", "File is written");
fileInputStream.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
Log.e("Debug", "error: " + ex.getMessage(), ex);
} catch (IOException ioe) {
Log.e("Debug", "error: " + ioe.getMessage(), ioe);
}
// ------------------ read the SERVER RESPONSE
try {
inStream = new DataInputStream(conn.getInputStream());
String str;
while ((str = inStream.readLine()) != null) {
Log.e("Debug", "Server Response " + str);
}
inStream.close();
} catch (IOException ioex) {
Log.e("Debug", "error: " + ioex.getMessage(), ioex);
}
}
**Edit: Just to be a little more clear, I would like it to where in my PHP script I could access values like $_REQUEST['path'] (which might = '/documents/' or something) as well as the actual file with $_FILES['uploadedfile']
String urlToSendRequest = "https://example.net";
String targetDomain = "example.net";
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpHost targetHost = new HttpHost(targetDomain, 80, "http");
HttpPost httpPost = new HttpPost(urlToSendRequest);
// Make sure the server knows what kind of a response we will accept
// httpPost.addHeader("Accept", "text/xml");
// Also be sure to tell the server what kind of content we are sending
httpPost.addHeader("Content-Type", "application/xml");
StringEntity entity = new StringEntity("<input>test</input>", "UTF-8");
entity.setContentType("application/xml");
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost, context);
Reader r = new InputStreamReader(response.getEntity().getContent());

Categories

Resources