Android: Как загрузить файл.mp3 на http-сервер?
Я хочу загрузить файл.mp3 (только) с устройства на мой сервер.
Я хочу просмотреть путь медиа-данных и выбрать любой mp3-файл и загрузить его.
Как я могу это сделать?
4 ответа
Мой последний рабочий код JAVA и PHP для загрузки файла с SD-карты Android на мой собственный веб-сервер.
Код Java/Android:
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);
}
}
Связанный PHP-код для отправки на ваш сервер (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;
}
?>
Вещи, чтобы отметить.
1) У меня был "mypic.png" в корневом каталоге SD-карты. Например, если вы посмотрите на устройство Android через USB-накопитель Mass Storage, вы поместите файл в первый каталог, с которым вы столкнетесь.
2) МАССОВОЕ ХРАНИЛИЩЕ USB ДОЛЖНО БЫТЬ ВЫКЛЮЧЕНО НА ТЕЛЕФОНЕ! Или просто полностью отключите его от компьютера, на котором вы пишете код, чтобы убедиться, что это так.
3) Я должен был создать папку "uploads" в той же директории, что и мой php-файл.
4) Очевидно, что вы должны изменить веб-адрес, который я написал как http://mywebsite.com/directory/upload.php на свой собственный веб-сайт.
Спасибо за хорошее предложение Китон.
Я немного упорядочил код Java, чтобы он был готов к использованию и добавил поддержку других параметров URL:
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();
}
}
}
Обратите внимание, что если вы скопируете и вставите вышеупомянутые коды PHP, любой может загрузить вредоносный сценарий PHP на ваш сервер и запустить его, всегда помните об этом, проверьте расширения SERVER SIDE с PHP, здесь и в Интернете тысячи примеров того, как сделай это. Также для дополнительной безопасности добавьте правила к вашему apache, серверу nginx, чтобы добавить заголовок Content-Disposition (jpg,png,gif,???) и НЕ анализировать код PHP в папке загрузки.
в nxgin например было бы что-то вроде этого...
#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;
}
Я знаю, что об этом спросили некоторое время. Я пытался реализовать то же самое, и после попытки многих решений я обнаружил, что код @Keaton работает для меня, но он блокировал мой пользовательский интерфейс (я использую Android Studio 2.1.2), поэтому мне пришлось обернуть его в AsyncTask.
Таким образом, используя код @Keaton у меня есть это.
Из моего onClickListener()
private View.OnClickListener btnUpload = new View.OnClickListener() {
@Override
public void onClick(View v) {
new doFileUpload().execute();
}
};
Тогда AsyncTask
public class doFileUpload extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
<Keaton's code>
return null;
}
}
Я надеюсь, что это помогает всем, кто сталкивается с той же проблемой, что и я.