28

I need to upload some data to PHP server. I can do post with parameters:

String url = "http://yourserver";

HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
nameValuePairs.add(new BasicNameValuePair("user", "username"));
nameValuePairs.add(new BasicNameValuePair("password", "password"));
try {
    httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
    httpClient.execute(httpPost);
}

I am also able to upload a file:

String url = "http://yourserver";
File file = new File(Environment.getExternalStorageDirectory(),
        "yourfile");
try {
    HttpClient httpclient = new DefaultHttpClient();

    HttpPost httppost = new HttpPost(url);

    InputStreamEntity reqEntity = new InputStreamEntity(
            new FileInputStream(file), -1);
    reqEntity.setContentType("binary/octet-stream");
    reqEntity.setChunked(true); // Send in multiple parts if needed
    httppost.setEntity(reqEntity);
    HttpResponse response = httpclient.execute(httppost);
    //Do something with response...
}

But how can I put it together? I need to upload an image and parameters in one post. Thanks

Kelib
  • 648
  • 2
  • 7
  • 15
  • adding the latest jar increases the size just by .2mb. – Vihaan Verma Nov 05 '14 at 07:16
  • Damn I've looked after a simple peace of code to upload an image, you sir saved me from a headache. Simply didn't understand that you just put an InputStreamEntity on it. I know there are other more complex ways but not what I needed. – Warpzit Mar 04 '15 at 19:55

5 Answers5

13

You have to use MultipartEntity. Find online and download those two libraries: httpmime-4.0.jar and apache-mime4j-0.4.jar and then you can attach as many stuff as desired. Here is example of how to use it:

HttpPost httpost = new HttpPost("URL_WHERE_TO_UPLOAD");
MultipartEntity entity = new MultipartEntity();
entity.addPart("myString", new StringBody("STRING_VALUE"));
entity.addPart("myImageFile", new FileBody(imageFile));
entity.addPart("myAudioFile", new FileBody(audioFile));
httpost.setEntity(entity);
HttpResponse response;
response = httpclient.execute(httpost);

and for server side you can use these entity identifier names myImageFile, myString and myAudioFile.

Markus W Mahlberg
  • 19,711
  • 6
  • 65
  • 89
Marcin S.
  • 11,161
  • 6
  • 50
  • 63
  • did you mean apache-mime4j-0.6.jar and httpmime-4.0.1.jar becuase I get "cant find org.....filed.Fields.content – wwjdm May 22 '13 at 21:47
  • yes, apache-mime4j-0.6.jar and httpmime-4.0.1.jar are the newer versions. – Marcin S. Jun 05 '13 at 22:52
  • In my client application it's getting crashed while executing this line **MultipartEntity entity = new MultipartEntity();**. I had included necessary jars. Any idea? – macOsX Aug 23 '13 at 09:03
  • This is not able to receive the data, at server side. All fields show as null, at the server! – Rohitesh Nov 16 '15 at 10:55
11

You must use a multipart http post, like in HTML forms. This can be done with an extra library. See the post Sending images using Http Post for a complete example.

Community
  • 1
  • 1
rgrocha
  • 1,461
  • 10
  • 19
4

This works like charm for me:

public int uploadFile(String sourceFileUri) {  

    String fileName=sourceFileUri;
    HttpURLConnection conn = null;
    DataOutputStream dos = null;  
    String lineEnd = "\r\n";
    String twoHyphens = "--";
    String boundary = "------hellojosh";
    int bytesRead, bytesAvailable, bufferSize;
    byte[] buffer;
    int maxBufferSize = 1 * 1024 * 1024; 
    File sourceFile = new File(fileName); 
    Log.e("joshtag", "Uploading: sourcefileURI, "+fileName);

    if (!sourceFile.isFile()) {                                
         Log.e("uploadFile", "Source File not exist :"+appSingleton.getInstance().photouri);//FullPath);                
         runOnUiThread(new Runnable() {
            public void run() {             
                //messageText.setText("Source File not exist :"
                }
            });          
         return 0;  //RETURN #1
         }
    else{
        try{                

             FileInputStream fileInputStream = new FileInputStream(sourceFile);           
             URL url = new URL(upLoadServerUri);
             Log.v("joshtag",url.toString());

             // 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            s       
             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("file", fileName);                     
             conn.setRequestProperty("user", user_id));

             dos = new DataOutputStream(conn.getOutputStream());  
             //ADD Some -F Form parameters, helping method
             //... is declared down below
             addFormField(dos, "someParameter", "someValue");

             dos.writeBytes(twoHyphens + boundary + lineEnd); 
             dos.writeBytes("Content-Disposition: form-data; name=\"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);
                    Log.i("joshtag","->");
                    }

             // 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().toString();              
             Log.i("joshtag", "HTTP Response is : "  + serverResponseMessage + ": " + serverResponseCode);  

             // ------------------ read the SERVER RESPONSE
             DataInputStream inStream;
             try {
                 inStream = new DataInputStream(conn.getInputStream());
                 String str;
                 while ((str = inStream.readLine()) != null) {
                     Log.e("joshtag", "SOF Server Response" + str);
                    }
                 inStream.close();
                }
             catch (IOException ioex) {
                Log.e("joshtag", "SOF error: " + ioex.getMessage(), ioex);
                }

             //close the streams //
             fileInputStream.close();
             dos.flush();
             dos.close();    

             if(serverResponseCode == 200){ 
                //Do something                       
                }//END IF Response code 200  

            dialog.dismiss();
            }//END TRY - FILE READ      
        catch (MalformedURLException ex) {
            ex.printStackTrace();     
            Log.e("joshtag", "UL error: " + ex.getMessage(), ex);  
            } //CATCH - URL Exception

         catch (Exception e) {           
            e.printStackTrace();             
            Log.e("Upload file to server Exception", "Exception : "+ e.getMessage(), e);
            } //

        return serverResponseCode; //after try       
        }//END ELSE, if file exists.
    }


public static String lineEnd = "\r\n";
public static String twoHyphens = "--";
public static String boundary = "------------------------afb19f4aeefb356c";
public static void addFormField(DataOutputStream dos, String parameter, String value){
    try {
        dos.writeBytes(twoHyphens + boundary + lineEnd);
        dos.writeBytes("Content-Disposition: form-data; name=\""+parameter+"\"" + lineEnd);
        dos.writeBytes(lineEnd);
        dos.writeBytes(value);
        dos.writeBytes(lineEnd);
    }
    catch(Exception e){

    }
}

UPDATE: If you need to send parameters along with the file, use:

conn.setRequestProperty("someParameter","someValue")
//or
addFormField(DataOutputStream dos, String parameter, String value)

...as shown in the code above. One or the other should work, if the server you are trying to connect to is not completely known to you.

Josh
  • 6,251
  • 2
  • 46
  • 73
  • 1
    only uploads the file without extra data! – Lazar Kukolj Mar 27 '16 at 06:34
  • what extra data? @user6042879 – Josh Mar 27 '16 at 10:46
  • @Josh What if I also need to send name-value pairs along with file? – Saeed Jassani Jun 16 '16 at 17:07
  • Good question @SaeedJassani I wanted to keep things simple but I will add a piece of code to my answer that does exactly what you need. – Josh Jun 20 '16 at 08:27
  • Why not? did you try passing the value pair as both .setRequestProperty or addFormField? @SaeedJassani – Josh Jun 22 '16 at 08:11
  • addFormField is not a method and according to the docs of .setRequestProperty it sets the request header field..... hence i cannot extract the values from the $_POST array on the server side – Saeed Jassani Jun 22 '16 at 08:38
  • Try addFormField, it is the helper method I put at the end of the code, just make sure you use the same boundary value during the entire POST. I used it to upload .wav and .png to some servers (which I have no access to) and it worked. @SaeedJassani – Josh Jun 22 '16 at 08:42
  • thanks @Josh .. eventually it worked... your code helped but it is not complete.. – Saeed Jassani Jun 23 '16 at 16:40
  • Glad it worked! every server is different so you need to code the client accordingly, The 1st step is to make sure your client creates valid Headers and Valuepairs. The 2nd part is tougher because you need to find out which parameter keynames and values satisfy the server, otherwise it complains with error 400 (bad request) or error 500. @SaeedJassani – Josh Jun 23 '16 at 19:23
1

be careful

MultiPartEntity and BasicNameValuePair are deprected .

So here is the new way to do it! And you only need httpcore.jar(latest) and httpmime.jar(latest) download them from Apache site.

try
{
    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(URL);

    MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
    entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);

    entityBuilder.addTextBody(USER_ID, userId);
    entityBuilder.addTextBody(NAME, name);
    entityBuilder.addTextBody(TYPE, type);
    entityBuilder.addTextBody(COMMENT, comment);
    entityBuilder.addTextBody(LATITUDE, String.valueOf(User.Latitude));
    entityBuilder.addTextBody(LONGITUDE, String.valueOf(User.Longitude));

    if(file != null)
    {
        entityBuilder.addBinaryBody(IMAGE, file);
    }

    HttpEntity entity = entityBuilder.build();
    post.setEntity(entity);
    HttpResponse response = client.execute(post);
    HttpEntity httpEntity = response.getEntity();
    result = EntityUtils.toString(httpEntity);
    Log.v("result", result);
}
catch(Exception e)
{
    e.printStackTrace();
}
Adnan Abdollah Zaki
  • 4,328
  • 6
  • 52
  • 58
  • this isn't working for me, the server is telling me "its not receiving all the parameters needed" and i only need 2, the photo and an id. – Diego Rivera Oct 13 '16 at 22:12
0

use this async Task.

    class httpUploader2 extends AsyncTask<Void, Void, Void> {
    private final static String boundary =  "*****M9J_cfALt*****";
    private final static String multiPartFormData = "multipart/form-data;boundary=" + boundary;
    @Override
    protected Void doInBackground(Void... params) {
        HttpURLConnection urlConnection = null;
        try {
            URL url = new URL("http://192.168.43.20/test.php");
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setConnectTimeout(5000);
            urlConnection.setRequestProperty("Connection", "Keep-Alive");
            urlConnection.setRequestProperty("Cache-Control", "no-cache");
            urlConnection.setRequestProperty("Content-Type", multiPartFormData);
            urlConnection.setUseCaches( false );
            urlConnection.setChunkedStreamingMode(0);

            DataOutputStream request = new DataOutputStream(urlConnection.getOutputStream());
            writeField(request,"hellow","world");
            writeFile(request,"file1","testfilename.txt","this is file content as string".getBytes(StandardCharsets.UTF_8));
            writeField(request,"testtt","valueeee");
            writeFile(request,"file2","testfilename2222.txt","this is file content as string".getBytes(StandardCharsets.UTF_8));
            request.flush();
            request.close();

            int code = urlConnection.getResponseCode();
            if (code ==  HTTP_OK) {
                //Log.d("@#$","Connected");
                BufferedReader rd = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                String line;
                while ((line = rd.readLine()) != null) {
                    Log.i("@#$", line);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }

        return null;
    }
    private void writeField(DataOutputStream request,String name,String value){
        String out = "\r\n--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"" + name +"\"";
        out += "\r\n\r\n" + value;
        try {
            request.write(out.getBytes(StandardCharsets.UTF_8));
        } catch (IOException ignored) {}
    }
    private void writeFile(DataOutputStream request,String name,String value,byte[] filedata){
        String out = "\r\n--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"" + name +"\"; filename=\"" + value + "\"";
        out += "\r\n\r\n";
        try {
            request.write(out.getBytes(StandardCharsets.UTF_8));
            request.write(filedata);
        } catch (IOException ignored) {}
    }
}

Use this php for testing(test.php) -

<?php
var_dump($_REQUEST);
echo "--------UPLOADED FILES--------\n";
var_dump($_FILES);
?>

I am using Android Pie on real testing device so need to declare this in manifest otherwise cannot connect-

<application
        android:usesCleartextTraffic="true"
.
.
/></application>

using xampp for testing php server. but you cant access it directly on your phone(real testing device). for that , first connect your PC to device hotspot. then in apache's httpd.txt - add Require all granted.

then to get ip address of your xampp for that hotspot network, write ipconfig and look for ipv4 address.

MbPCM
  • 457
  • 5
  • 12