Android:How to upload .mp3 file to http server?
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;
}