19

I want to upload .mp3 file(only) from device to my server.

I want to browse path of media data and select any mp3 file and upload it.

How can I do this?

Piyush
  • 2,589
  • 6
  • 38
  • 77

4 Answers4

37

My final working JAVA and PHP code to upload a file from the Android's SD card to my own Web Server.

The Java/Android Code:

private void doFileUpload() {

    HttpURLConnection conn = null;
    DataOutputStream dos = null;
    DataInputStream inStream = null;
    String existingFileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/mypic.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://mywebsite.com/directory/upload.php";

    try {

        //------------------ CLIENT REQUEST
        FileInputStream fileInputStream = new FileInputStream(new File(existingFileName));
        // 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=\"" + existingFileName + "\"" + 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);
    }
}

The associated PHP code to go on your server (upload.php):

<?php
// Where the file is going to be placed 
$target_path = "uploads/";

/* Add the original filename to our target path.  
Result is "uploads/filename.extension" */
$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";
    chmod ("uploads/".basename( $_FILES['uploadedfile']['name']), 0644);
} else{
    echo "There was an error uploading the file, please try again!";
    echo "filename: " .  basename( $_FILES['uploadedfile']['name']);
    echo "target_path: " .$target_path;
}
?>

Things to note.
1) I had "mypic.png" within the root directory of the SD card. As in, if you looked at the Android device through Mass Storage USB view you would put the file in the first directory you come across.

2) USB MASS STORAGE MUST BE TURNED OFF ON THE PHONE! Or just completely unplug it from the computer you are writing the code on to assure this is the case.

3) I had to create an "uploads" folder in the same directory as my php file.

4) You obviously must change the web address I have written as http://mywebsite.com/directory/upload.php to be your own website.

Nikhil Agrawal
  • 26,128
  • 21
  • 90
  • 126
Keaton
  • 386
  • 3
  • 2
  • can you tell me how we can post a simple string data along with the multipart posting... i want to send an parameter with name postingname... – Dinash May 16 '11 at 14:03
  • Great sample code :-) In my case I had to do basic authentication first which was easily handled by: 'Authenticator.setDefault (new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication ("username", "password".toCharArray()); } });' I figured someone else might be interested in knowing my solution to this. – Lasse Samson Nov 10 '11 at 09:53
  • @Keaton my file is uploading but the uploaded file size is always 0. What could be the mater. I used the same source from this [link](http://reecon.wordpress.com/2010/04/25/uploading-files-to-http-server-using-post-android-sdk/) Thanks in advance – AnujAroshA Feb 03 '12 at 10:22
  • @Keaton sorry for disturbing you. I found the error. I just put the greater than sign in other way around :-) – AnujAroshA Feb 03 '12 at 11:22
  • @Keaton is it necessary to write the code that is after //------------------ read the SERVER RESPONSE line – dira Jul 02 '12 at 14:07
  • Nice example @keaton ,can you tell me how do i compress or reduce the size of image before uploading it on server? – Juned Sep 05 '12 at 10:30
  • As for The associated PHP code to go on your server (upload.php): How to constrcut the Java Servlet Version ? – Jeff Bootsholz Jul 11 '13 at 04:33
  • PHP code is not working for me. I'm getting this reply. I'm uploading a mp4 file. Server Response There was an error uploading the file, please try again!filename: VID_20130730_100113.mp4target_path: uploads/VID_20130730_100113.mp4 Any suggestions ? – Chrishan Jul 31 '13 at 10:15
  • It is gives an error `FileNotFoundException` on Server, I think `POST` are not reach in file. – Pratik Butani Jun 02 '14 at 10:12
  • This **worked** very well for me! Just remember to put a folder in the **same directory** as the **php-file** ! And also put the method in an AsyncTask – ymerdrengene Jul 29 '14 at 12:25
  • This worked very well for me too. thank you. if i may add as a reminder always make sure the uploads folder is writeable. I got caught up on the file permission for a few minutes before I realized. – gilsaints88 Jan 21 '15 at 04:08
6

Thanks for the good suggestion Keaton.

I've arranged the Java code a bit so it's ready to use and to add support for other URL parameters:

public class HttpMultipartUpload {
    static String lineEnd = "\r\n";
    static String twoHyphens = "--";
    static String boundary = "AaB03x87yxdkjnxvi7";

    public static String upload(URL url, File file, String fileParameterName, HashMap<String, String> parameters)
            throws IOException {
        HttpURLConnection conn = null;
        DataOutputStream dos = null;
        DataInputStream dis = null;
        FileInputStream fileInputStream = null;

        byte[] buffer;
        int maxBufferSize = 20 * 1024;
        try {
            //------------------ CLIENT REQUEST
            fileInputStream = new FileInputStream(file);

            // open a URL connection to the Servlet
            // 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("Content-Type", "multipart/form-data;boundary=" + boundary);

            dos = new DataOutputStream(conn.getOutputStream());

            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=\"" + fileParameterName
                    + "\"; filename=\"" + file.toString() + "\"" + lineEnd);
            dos.writeBytes("Content-Type: text/xml" + lineEnd);
            dos.writeBytes(lineEnd);

            // create a buffer of maximum size
            buffer = new byte[Math.min((int) file.length(), maxBufferSize)];
            int length;
            // read file and write it into form...
            while ((length = fileInputStream.read(buffer)) != -1) {
                dos.write(buffer, 0, length);
            }

            for (String name : parameters.keySet()) {
                dos.writeBytes(lineEnd);
                dos.writeBytes(twoHyphens + boundary + lineEnd);
                dos.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"" + lineEnd);
                dos.writeBytes(lineEnd);
                dos.writeBytes(parameters.get(name));
            }

            // send multipart form data necessary after file data...
            dos.writeBytes(lineEnd);
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
            dos.flush();
        } finally {
            if (fileInputStream != null) fileInputStream.close();
            if (dos != null) dos.close();
        }

        //------------------ read the SERVER RESPONSE
        try {
            dis = new DataInputStream(conn.getInputStream());
            StringBuilder response = new StringBuilder();

            String line;
            while ((line = dis.readLine()) != null) {
                response.append(line).append('\n');
            }

            return response.toString();
        } finally {
            if (dis != null) dis.close();
        }
    }
}
Pierre-Luc Paour
  • 1,725
  • 17
  • 21
1

Notice if you copy & paste the above PHP codes anyone could upload a malicious PHP script to your server and run it, always be aware of that, check the extensions SERVER SIDE with PHP there are thousands of examples here and in the web on how to do it. Also for extra security add rules to your apache, nginx server to add header Content-Disposition (jpg,png,gif,???) and to NOT parse PHP code on the upload folder.

in nxgin for example it would be something like this...

#add header Content-Disposition
location ^~ /upload/pictures {

        default_type application/octet-stream;

    types {
            image/gif     gif;
            image/jpeg    jpg;
            image/png    png;
    }

    add_header X-Content-Type-Options 'nosniff';

    if ($request_filename ~ /(((?!\.(jpg)|(png)|(gif)$)[^/])+$)) {
        add_header Content-Disposition 'attachment; filename="$1"';
            # Add X-Content-Type-Options again, as using add_header in a new context
            # dismisses all previous add_header calls:
            add_header X-Content-Type-Options 'nosniff';
        }
}

#do NOT parse PHP script on the upload folder
location ~ \.php$ {
    try_files $uri =404;
    include /etc/nginx/fastcgi_params;
    #if is the upload folder DO NOT parse PHP scripts on it
    if ($uri !~ "^/upload/pictures") {
        fastcgi_pass unix:/var/run/php-fastcgi/php-fastcgi.socket;
    }
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
D.Snap
  • 1,704
  • 1
  • 22
  • 15
0

I know this was asked a while aback. I was trying to implement the same and after trying many solutions I found that @Keaton 's code is working for me, but it was blocking my UI (I am using Android Studio 2.1.2), so I had to wrap it in an AsyncTask.

So using @Keaton 's code I have this.

From my onClickListener()

private View.OnClickListener btnUpload = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        new doFileUpload().execute();
    }
};

Then the AsyncTask

public class doFileUpload extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {

        <Keaton's code>

     return null;
   }
}

I hope this helps to anybody having the same problem I had.

Erik
  • 57
  • 1
  • 9