Android:How to upload .mp3 file to http server?-ThrowExceptions

Exception or error:

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?

How to solve:

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.

###

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();
        }
    }
}

###

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;
}

###

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.

Leave a Reply

Your email address will not be published. Required fields are marked *