Подтвердить что ты не робот

Android: Как загрузить файл .mp3 на http-сервер?

Я хочу загрузить .mp3 файл (только) с устройства на свой сервер.

Я хочу просмотреть путь к медиаданным и выбрать любой mp3 файл и загрузить его.

Как я могу это сделать?

4b9b3361

Ответ 1

Мой последний рабочий 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 MASS STORAGE ДОЛЖЕН БЫТЬ ВЫКЛЮЧЕН НА ТЕЛЕФОНЕ! Или просто полностью отключите его от компьютера, на котором вы пишете код, чтобы убедиться в этом.

3) Мне пришлось создать папку "uploads" в том же каталоге, что и мой php файл.

4) Очевидно, вы должны изменить веб-адрес, который я написал как http://mywebsite.com/directory/upload.php, чтобы быть вашим собственным веб-сайтом.

Ответ 2

Спасибо за хорошее предложение Китон.

Я немного упорядочил 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();
        }
    }
}

Ответ 3

Обратите внимание, что если вы копируете и вставляете вышеуказанные 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 скрипт on the upload folder
location ~ \.php$ {
    try_files $uri =404;
    include /etc/nginx/fastcgi_params;
    #if is the upload folder DO NOT parse PHP скриптs 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;
}

Ответ 4

Я знаю, что это было немного озадачено. Я пытался реализовать то же самое, и, попробовав множество решений, я обнаружил, что Для меня работает код @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 code>

     return null;
   }
}

Надеюсь, это поможет любому, у кого была такая же проблема.