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.
Related
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.....
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.
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());
Thank you in advance.
I'd like to upload some bitmap image from my android app.
but , I can't get it.
Could you recommend some solutions for it.
or collect my source code?
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, bao);
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(
"http://example.com/imagestore/post");
MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE );
byte [] ba = bao.toByteArray();
try {
entity.addPart("img", new StringBody(new String(bao.toByteArray())));
httppost.setEntity(entity);
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// Execute HTTP Post Request
HttpResponse response = null;
try {
response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
}
use httpmime for uploading Image
try this
http://vikaskanani.wordpress.com/2011/01/11/android-upload-image-or-file-using-http-post-multi-part/
I found this solution really well created and 100% working even with amazon ec2, take a look into this link:
Uploading files to HTTP server using POST on Android (link deleted).
Compare to previous answer, this solution doesn't require to import huge library httpmime from Apache.
Copied text from original article:
This tutorial shows a simple way of uploading data (images, MP3s, text files etc.) to HTTP/PHP server using Android SDK.
It includes all the code needed to make the uploading work on the Android side, as well as a simple server side code in PHP to handle the uploading of the file and saving it. Moreover, it also gives you information on how to handle the basic autorization when uploading the file.
When testing it on emulator remember to add your test file to Android’s file system via DDMS or command line.
What we are going to do is set the appropriate content type of the request and include the byte array as the body of the post. The byte array will contain the contents of a file we want to send to the server.
Below you will find a useful code snippet that performs the uploading operation. The code includes also server response handling.
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
DataInputStream inputStream = null;
String pathToOurFile = "/data/file_to_send.mp3";
String urlServer = "http://192.168.1.1/handle_upload.php";
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1*1024*1024;
try
{
FileInputStream fileInputStream = new FileInputStream(new File(pathToOurFile) );
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
// Allow Inputs & Outputs.
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// Set HTTP method to POST.
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
outputStream = new DataOutputStream( connection.getOutputStream() );
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + pathToOurFile +"\"" + 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);
// Responses from the server (code and message)
serverResponseCode = connection.getResponseCode();
serverResponseMessage = connection.getResponseMessage();
fileInputStream.close();
outputStream.flush();
outputStream.close();
}
catch (Exception ex)
{
//Exception handling
}
If you need to authenticate your user with a username and password while uploading the file, the code snippet below shows how to add it. All you have to do is set the Authorization headers when the connection is created.
String usernamePassword = yourUsername + “:” + yourPassword;
String encodedUsernamePassword = Base64.encodeToString(usernamePassword.getBytes(), Base64.DEFAULT);
connection.setRequestProperty (“Authorization”, “Basic ” + encodedUsernamePassword);
Let’s say that a PHP script is responsible for receiving data on the server side. Sample of such a PHP script could look like this:
<?php
$target_path = "./";
$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!";
}
?>;
Code was tested on Android 2.1 and 4.3. Remember to add permissions to your script on server side. Otherwise, the uploading won’t work.
chmod 777 uploadsfolder
Where uploadsfolder is the folder where the files are uploaded. If you plan to upload files bigger than default 2MB file size limit. You will have to modify the upload_max_filesize value in the php.ini file.
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);